Computer Organization Lab Manual
Computer Organization Lab Manual
1403372
Computer Organization
Lab Manual
TABLE OF CONTENTS
Table of Contents ........................................................................................................................ i
The above general laboratory safety rules are designed to safeguard you and your co-workers, fellow
students and colleagues and are a minimum requirement for individuals working in the computer
engineering laboratories at Umm Al-Qura University, Makkah Al-Mukarramah. Specialized training
and rules may apply depending on type and scope of activities involved.
MARS is a software simulator for the MIPS assembly language intended for educational use. We
will explore the capabilities of MARS release 4.3.
2. Use the menubar File…Open or the Open icon to open Fibonacci.asm in the default
folder. (All icons have menubar equivalents; the remainder of these steps will use the icon
whenever possible.)
3. The provided assembly program is complete. Assemble the program using the icon
4. Identify the location and values of the program’s initialized data. Use the checkbox to toggle
the display format between decimal and hexadecimal .
• The nineteen-element array fibs is initialized to zero, at addresses 0x10010000 …
0x10010048.
• The data location size has value 19ten at 0x1001004c.
• The addresses 0x10010050 … 0x1001006c contain null-terminated ASCII strings.
Use the checkbox to toggle the display format between decimal and hexadecimal,
.
5. Use the Settings menu to configure the MARS displays. The settings will be retained for the
next MARS session.
• The Labels display contains the addresses of the assembly code statements with a label,
but the default is to not show this display. Select the checkbox from the Settings menu.
7. Use the slider bar to change the run speed to about 10 instructions per second.
• The icon runs the program to completion. Using this icon, you should observe the
yellow highlight showing the program’s progress and the values of the Fibonacci
sequence appearing in the Data Segment display.
• The icon resets the program and simulator to initial values. Memory contents are
those specified within the program, and register contents are generally zero.
9. Observe the output of the program in the Run I/O display window:
The Fibonacci numbers are:
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181
-- program is finished running --
10. Modify the contents of memory. (Modifying a register value is exactly the same.)
• Set a breakpoint at the first instruction of the subroutine which prints results. Use the
checkbox at the left of the instruction whose address is 0x00400060 = 4194400ten.
• Click to continue from the breakpoint. The program output includes your entered
value instead of the computed Fibonacci number.
11. Open the Help for information on MIPS instructions, pseudo instructions, directives,
and syscalls.
• Select the Edit tab in the upper right to return to the program editor.
• The MIPS comment symbol is #. All characters on the line after the character # are
ignored.
• Un-comment lines 12-19. The newly exposed program fragment will prompt the user for
the length of the Fibonacci sequence to generate, in the range 2 ≤ x ≤ 19 . (The length of
the sequence must be limited to the size of the declared space for result storage.)
• Determine the correct syscall parameter to perform “read integer” from the user, and
insert the parameter at line The correct syscall parameter may be found at Help
… Syscall tab…read integer service. The completed line will have the form li $v0, 42
(where in this case 42 is not the right answer).
• Reset and re-run the program. The program will stop at the breakpoint you
Data types:
Literals:
Registers
• 32 general-purpose registers
• register preceded by $ in assembly language instruction
two formats for addressing:
o using register number e.g. $0 through $31
o using equivalent names e.g. $t1, $sp
• special registers Lo and Hi used to store result of multiplication and division
o not directly addressable; contents accessed with special instruction mfhi
("move from Hi") and mflo ("move from Lo")
• stack grows from high memory to low memory
Register Alternative
Description
Number Name
0 zero the value 0
1 $at (assembler temporary) reserved by the assembler
2-3 $v0 - $v1 (values) from expression evaluation and function results
(arguments) First four parameters for subroutine.
4-7 $a0 - $a3
Not preserved across procedure calls
(temporaries) Caller saved if needed. Subroutines can use w/out saving.
8-15 $t0 - $t7
Not preserved across procedure calls
Data Declarations
Code
Comments
Put the sum of the integers from register Rsrc1 and Src2 (or Imm) into
register Rdest.
Similar to add, we have instruction for subtraction ‘sub’. It works in the same
manner as addition instruction. Examples of addition and subtraction are:
This instruction is used to store an immediate value imm into the register Rdest.
Example of li instruction can be:
First two instructions are used to store the values in registers $t0 and $t1. Line 3 will
add these 2 registers and result will be stored in register $t2 and line 4 will subtract
$t1, $t0 and the result will be stored in register $t3.
A number of system services, mainly for input and output, are available for use by
your MIPS program. They are described in the table below.
MIPS register contents are not affected by a system call, except for result registers as
specified in the table below.
Termination of Program:
System call code ‘10’ is used to terminate the program. To terminate the executing
program, the value ‘10’ is required to be copied to register $v0 and then the instruction
syscall will be executed to perform the termination task.
li $v0, 10
syscall
Integer Input:
System call code ‘5’ is used to get an integer input. After calling the syscall, user has to
input the number. This input is stored in the register $v0. Which has to be moved to some
other register before proceeding forward.
li $v0, 5
syscall
Integer Output:
System call code ‘1’ is used to display an integer value on the screen. The value must be
stored in the register $a0 hence before calling syscall, we have to move the required value
to the register $a0. In the below example, we want to display the value of register $t0, so
we have moved the contents of register $t0 to the register $a0
move is data movement instruction. The number of operands required for the move
instruction in two. One of them is source while the other is destination. The general
syntax of move instruction is:
Where Rdest is the destination register while Rsrc is the source register and we are
moving value from Rsrc to Rdest.
The third operand in the instruction is the offset. In MIPS, this is a 16 bit signed integer
that represents where to continue if the comparison returns true. The offset represents
how many instructions, counting from the instruction after the branch instruction, to pass
over in order to get to the correct instruction. For example look at the code below:
In this code, the branch instruction would move up two instructions from the instruction
after itself. This means it would branch from position 0x4000:0008 to position
0x4000:0000 and then continue evaluating the instructions in sequence. It works going in
the opposite direction as well.
In the case above, the branch would go from position 0x4000:0010 to position
0x4000:0014 before continuing evaluation of the instruction in sequence. Notice that the
total number of bytes skipped is found by multiplying offset by 4.
if (pred) consequent
If consists of both a predicate and a consequent. The predicate is itself a single expression
that results in either a “true” or “false” value (non-zero or zero value). The consequent is
a single statement expression, or multiple statement expressions surrounded by braces,
‘{’ and ‘}’. We can make a similar construct using MIPS assembly code:
In the above code, if the condition is true, the processor will jumps to the endif. If the
condition is false, the processor won’t jumps, rather it will execute the very next line after
the branch statement (in this case: the consequent portion).
Notice that we can divide our MIPS code into three regions, the predicate, the branch
statement, and the consequent. The first of these regions is the predicate. Any number of
statements that produce a zero or non-zero value in a register. The second region is the
branch statement. If beq is used with $zero, a non-zero value would be true, and if bne is
used with $zero, a zero value would be true. The third region is the consequent. This does
whatever should be done if a true value results.
j endif # else
In the above piece of code, two registers $s1 and $s2 is compared. If $s1 is not equal to
$s2 then register $s1 is incremented by ‘1’. Otherwise the value of register $s2 is
incremented. After execution of true part, the code jumps to the endif statement; so that it
doesn’t execute the false part of this branch statement.
Notice the use of the jump instruction for MIPS. This instruction jumps without condition
to the location given. The location is specified by a 28bit number. There is also an
instruction that jumps without condition to the location given inside a register.
Main:
li $v0, 5
syscall
move $t0, $v0
li $v0, 5
syscall
move $t1, $v0
out: li $v0, 10
syscall
We'll consider several jump instructions, which is used to implement certain branches
that don't exist as instructions MIPS.
main:
li $v0, 5
syscall
li $v0, 5
syscall
out: li $v0, 10
syscall
The loops are also implemented by using the branch statement (discussed in previous
labs). All type of loops (for, while, and do-while) can be implement by using branch
statements.
In the above code, if the condition is true ($s1 > $s2), the code will jumps to the endwhile
and the loop will stop execution. On other hand, the loop will executes till the value of
register $s1 is less than the value of register $s2. After incrementing the value of register
$s1, the code takes an unconditional jump to the start of the loop.
We have executed the body of loop without checking the condition. Condition will be
checked after executing the body of loop and the execution of next iteration depends
upon the result of this condition checking statement. Hence the body of the loop will be
executed at least once whether the given condition is true or false.
Notice how it’s form doesn’t really change that much from the while loop. It’s really just
a construct in C to make code more compressed and readable.
Divide Instruction:
The general syntax of instruction used for division of two numbers is
In the above example, the register $t0 is divided by the register $t1. In this instruction, we
don’t mention the output register like we do in add and sub instruction. Two special
registers are used for storing the results. These register are lo and hi. Hence div
instruction is equivalent to:
lo = $t0 / $t1
hi = $t0 % $t1
In other words, it sets lo register to the quotient and hi register to the remainder of
dividing its two integer operands. Since these two registers are not programmable (i.e.
cannot be referenced in a program), the two instructions: mflo (move-from-lo) and
mfhi (move-from-hi) were added to the instruction set to facilitate copying the contents
of lo and hi to programmable registers. The use of div instruction is illustrated by the
following example:
main:
addi $t0, $0, 60
addi $t1, $0, 7
div $t0, $t1
mflo $a0
Register $t0 is divided by register $t1 and the contents of register lo are moved to register
$a0. These two register lo and hi can only be accessible through mflo and mfhi
commands.
Multiply Instruction:
The general syntax of instruction used for multiply of two numbers is
In the above example, the register $t0 is multiplied by the register $t1. In this instruction,
we don’t mention the output register like we do in add and sub instruction. Two special
registers are used for storing the results. These register are lo and hi. When we multiply
Department of Computer Engineering, Umm Al-Qura University Page 21 of 34
two 32-bit register, the size of resultant is 64-bit. Hence we require two 32-bit register to
store the complete result of the multiplication process. So the lower 32-bits of the result
are stored in the register lo while the higher 32-bits are stored in the register hi.
As discussed earlier, these two registers are not programmable (i.e. cannot be referenced
in a program), the two instructions: mflo (move-from-lo) and mfhi (move-from-hi)
were added to the instruction set to facilitate copying the contents of lo and hi to
programmable registers. The use of mult instruction is illustrated by the following
example:
main:
addi $t0, $0, 60
addi $t1, $0, 7
mult $t0, $t1
mfhi $a0
Register $t0 is multiplied by register $t1 and the contents of register lo are moved to
register $a0. These two register lo and hi can only be accessible through mflo and mfhi
commands.
main: #---------------------
addi $t0, $0, 60
addi $t1, $0, 7
div $t0, $t1
mflo $a0
li $v0,1
syscall
mfhi $a1
li $v0,1
move $a0,$a1
syscall
o create storage for variable of specified type with given name and specified
value
o value(s) usually gives initial value(s); for storage type .space, gives number
of spaces to be allocated
example
load:
lw register_destination, RAM_source
store word:
sw register_source, RAM_destination
example:
.data
var1: .word 23 # declare storage for var1; initial value is 23
.text
__start:
lw $t0, var1 # load contents of RAM location into
register $t0: $t0 = var1
li $t1, 5 # $t1 = 5 ("load immediate")
sw $t1, var1 # store contents of register $t1 into
RAM: var1 = $t1
done
load address:
la $t0, var1
indirect addressing:
lw $t2, ($t0)
example
.data
array1: .space 12 # declare 12 bytes of storage to hold
array of 3 integers
.text
__start: la $t0, array1 # load base address of array
into register $t0
li $t1, 5 # $t1 = 5 ("load immediate")
sw $t1, ($t0) # first array element set to 5;
indirect addressing
li $t1, 13 # $t1 = 13
sw $t1, 4($t0) # second array element set to 13
li $t1, -7 # $t1 = -7
sw $t1, 8($t0) # third array element set to -7
done
That means that, for example, we can store 5 values of type int in an array without having
to declare 5 different variables, each one with a different identifier. Instead of that, using
an array we can store 5 different values of the same type, int for example, with a unique
identifier.
Since arrays can store LOTS of data, and since we have only a small (~32) number of
registers, it is infeasible to use the registers for long-term storage of the array
data. Hence, arrays are stored in the Data Segment of a MIPS
program. Fundamentally, there are three operations which one can perform on an
array:
For purposes of this step in the lab, you may assume that the length of the array is
10. (The worksheet asks about changing this, but you may hard code this value while
writing the program.)
To access the data in the array requires that we know the address of the data and then
use the load word (lw) or store word (sw) instructions. Words (which is how integers
are stored) in MIPS take up 32 bits or 4 bytes. Therefore, if we have a declaration
such as:
the address that is loaded by the instruction la $t3, list is the address of the
first '3' in the list. The address of the '0' is 4 greater than that number, and the address
of the '6' is 16 greater than that number.
The following snippet of code will place the value of list[6] into the $t4:
If we wish to assign to the contents of $t4 to list[6] instead, the last line would
simply be:
.data
A: .word 3,4,5,6,7
B: .word 1,2,3,4,5
C: .word 0:5
.text
main:
la $s0, A
la $s1, B
la $s2, C
li $t5,0
li $t6,5
Loop:
lw $t1, ($s0)
lw $t2, ($s1)
sw $t3, ($s2)
j Loop
out:
li $v0, 10
syscall
lb $s2, 3($s1)
sb $s2, -2($s1)
lb takes one byte from memory and puts it into a register. The upper 24 bits of the
register are sign extended i.e. filled with whatever value is in the most significant bit
(MSB) of that byte. There is also an unsigned version of load byte, namely lbu, which
fills the upper 24 bits with 0’s (regardless of the MSB).
sb copies the lower 8 bits of a register into some byte in memory. This instruction ignores
the upper 24 bits of the word in the register.
Storage type (required for the variable declaration) for the string is either .ascii or .asciiz.
Difference between these two is; in case of .asciiz, a string terminating character (null
character) is automatically inserted at the end of the string while in case of .ascii, no
string terminating character is added. The contents of the string are enclosed by quotes
and the syscall for displaying the string on the screen require the value ‘4’ in the register
$v0 while the address of the string must be in the register $a0.
.data
str: .asciiz “hello world”
.text
main:
la $a0, str
li $v0, 4
syscall
li $v0, 10
syscall
Program: Counting the number of characters in a string. Register $t1 will contain the result.
.data
str: .asciiz “hello world”
.text
main:
la $t0, str
li $t1, 0
lb $t2, ($t0)
start:
beqz $t2, endloop
add $t1, $t1, 1
add $t0, $t0, 1
lb $t2, ($t0)
j start
endloop:
li $v0, 10
syscall
Format Types:
There are three types of instruction formats, R-format, I-format, and J-format. The R stands for a
register-format instruction, an I stands for an immediate-format instruction, and a J stands for a
jump-format instruction. The R-format instructions mainly handle only the register instructions
because three of the fields in the format tell the MIPS processor what registers are being used.
The operation field is 6 bits and is found in all of the formats, in the exact same location
as shown above. This field tells the microprocessor, not only what type of instruction is
being evaluated, but what type of format is being used. In the R-format, the source and
transition register fields tell the microprocessor which registers will be acting as source
registers (registers left unchanged by the operation; only their value is used). The
destination register field, only existing in the R-format, indicates which register will hold
the final value of an operation. The shift amount field is used in shift operations to
indicate how much to shift a given register. Notice that it is 5 bits, so it can shift 32 bits.
The function field, possibly getting it’s name from “math functions”, is used in addition
to the operation field for determining the type of R-format instruction.
The J-format is only capable of operating given a constant value, an address. Some
special J-format instructions do operate on registers, even though they aren’t specified
directly. The target address field only contains addresses. If an address in excess of a 28
bit value3 is needed, a register can be used to hold the address.