# Hello, World!
.data ## Data declaration section
## String to be printed:
out_string: .asciiz “\nHello, World!\n”
.text
main:
## Assembly language instructions go in text segment ## Start of code section
li
la syscall
$v0, 4
$a0, out_string
# system call code for printing string = 4
# load address of string to be printed into $a0 # call operating system to perform operation
# specified in $v0
# syscall takes its arguments from $a0, $a1, …
# terminate program
li $v0, 10
syscall
This illustrates the basic structure of an assembly language program.
– data segment and text segment
– use of label for data object (which is a zero-terminated ASCII string) – useofregisters
– invocation of a system call
MIPS Hello World MIPS Assembly 1
CS@VT Computer Organization II ý2005-2015 McQuain
MIPS assemblers support standard symbolic names for the general-purpose registers:
$zero stores value 0; cannot be modified
$v0-1 used for system calls and procedure return values $a0-3 used for passing arguments to procedures
$t0-9 used for local storage; calling procedure saves these $s0-7 used for local storage; called procedure saves these
And for the reserved registers:
$sp stack pointer
$fp frame pointer; primarily used during stack manipulations $ra used to store return address in procedure call
$gp pointer to area storing global data (data segment)
$at reserved for use by the assembler $k0-1 reserved for use by OS kernel
MIPS Register Names MIPS Assembly 2
CS@VT Computer Organization II ý2005-2015 McQuain
All arithmetic and logical instructions have 3 operands Operand order is fixed (destination first):
Example:
Ccode: MIPS code:
a = b + c;
add $s0, $s3, $s2
¡°The natural number of operands for an operation like addition is three…requiring every instruction to have exactly three operands, no more and no less, conforms to the philosophy of keeping the hardware simple¡±
MIPS Arithmetic Instructions MIPS Assembly 3
CS@VT Computer Organization II ý2005-2015 McQuain
Here are the most basic arithmetic instructions:
add $rd,$rs,$rt
div $rs,$rt
mul $rd,$rs,$rt
sub $rd,$rs,$rt
Addition with overflow
GPR[rd] <-- GPR[rs] + GPR[rt] Division with overflow
$lo <-- GPR[rs]/GPR[rt]
$hi <-- GPR[rs]%GPR[rt] Multiplication without overflow GPR[rd] <-- (GPR[rs]*GPR[rt])[31:0] Subtraction with overflow
GPR[rd] <-- GPR[rs] - GPR[rt]
Instructions "with overflow" will generate an runtime exception if the computed result is too large to be stored correctly in 32 bits.
There are also versions of some of these that essentially ignore overflow, like addu.
Basic MIPS Arithmetic Instructions MIPS Assembly 4
CS@VT Computer Organization II ý2005-2015 McQuain
Design Principle: simplicity favors regularity.
Of course this complicates some things...
Ccode: a = b + c + d;
MIPS pseudo-code: add $s0, $s1, $s2 add $s0, $s0, $s3
Operands must be registers (or immediates), only 32 registers are provided Each register contains 32 bits
Design Principle: smaller is faster.
Why?
Limitations and Trade-offs MIPS Assembly 5
CS@VT Computer Organization II ý2005-2015 McQuain
In MIPS assembly, immediates are literal constants.
Many instructions allow immediates to be used as parameters.
addi $t0, $t1, 42 # note the opcode
li $t0, 42 # actually a pseudo-instruction
Note that immediates cannot be used with all MIPS assembly instructions; refer to your MIPS reference card.
Immediates may also be expressed in hexadecimal: 0x2A
Immediates MIPS Assembly 6
CS@VT Computer Organization II ý2005-2015 McQuain
Logical instructions also have three operands and the same format as the arithmetic instructions:
Examples:
and $s0, $s1, $s2 andi $s0, $s1, 42 or $s0, $s1, $s2 ori $s0, $s1, 42
# bitwise AND
# bitwise OR
# bitwise NOR (i.e., NOT OR) # logical shift left
# logical shift right
nor $s0, sll $s0, srl $s0,
$s1, $s2 $s1, 10 $s1, 10
MIPS Logical Instructions MIPS Assembly 7
CS@VT Computer Organization II ý2005-2015 McQuain
Transfer data between memory and registers
Example:
Ccode: A[12] = h + A[8];
MIPS code: lw $t0, 32($s3) add $t0, $s2, $t0
# $t0 <-- Mem[$s3+32]
# Mem[$s3+48] <-- $t0
sw $t0, 48($s3)
Can refer to registers by name (e.g., $s2, $t2) instead of number
Loadcommandspecifiesdestinationfirst: opcode
MIPS Load and Store Instructions MIPS Assembly 8
CS@VT Computer Organization II ý2005-2015 McQuain
In MIPS assembly, a label is simply a string used to name a location in memory. A label may refer to the location of a data value (variable) or of an instruction. In essence, think of a label as representing an address.
Labels are terminated by a colon character.
.data
N: .word 10
.text main:
exit: li $v0, 10
syscall
lw $t0, N la $t1, N …
# $t0 <-- Mem[N] (10)
# $t1 <-- N (address)
Labels MIPS Assembly 9
CS@VT Computer Organization II ý2005-2015 McQuain
In register mode the address is simply the value in a register:
lw $t0, ($s3) # use value in $s3 as address
In immediate mode the address is simply an immediate value in the instruction: lw $t0, 0 # almost always a bad idea
In base + register mode the address is the sum of an immediate and the value in a register:
lw $t0, 100($s3) # address is $s3 + 100 There are also various label modes:
lw $t0, absval # absval is a label lw $t0, absval + 100
lw $t0, absval + 100($s3)
Addressing Modes MIPS Assembly 10
CS@VT Computer Organization II ý2005-2015 McQuain
MIPS unconditional branch instructions:
j Label b Label jr $ra
# PC = Label # PC = Label # PC = $ra
These are useful for building loops and conditional control structures.
Unconditional Branch Instructions MIPS Assembly 11
CS@VT Computer Organization II ý2005-2015 McQuain
Decision making instructions
- alter the control flow,
- i.e., change the "next" instruction to be executed
MIPS conditional branch instructions:
bne $t0, $t1,
# $s3 == i, $s4 == j
slt $t1, $s3, $s4
beq $zero, $t1, B
A: # code…
bC
B: # code…
C:
if ( i < j )
goto A;
else
goto B;
Conditional Control Structure MIPS Assembly 13
CS@VT Computer Organization II ý2005-2015 McQuain
int Sum = 0;
for (int i = 1; i <= N; ++i) {
Sum = Sum + i; }
# $s0 == Sum, $s1 == N, $t0 == i
lw
li loop: beq add
$s1, N
$t0, 1
$t0, $s1, done $s0, $s0, $t0
done:
move $s0, $zero
# register assignment # assume global symbol # literal assignment
# loop test
# Sum = Sum + i
# ++i
# restart loop
addi $t0, $t0, 1
b loop
for Loop Example MIPS Assembly 14
CS@VT Computer Organization II ý2005-2015 McQuain
MIPS programmers are expected to conform to the following conventions when using the 29 available 32-bit registers:
Name
Register number
Usage
$zero
0
the constant value 0
$v0-$v1
2-3
values for results and expression evaluation
$a0-$a3
4-7
arguments
$t0-$t7
8-15
temporaries
$s0-$s7
16-23
saved
$t8-$t9
24-25
more temporaries
$gp
28
global pointer
$sp
29
stack pointer
$fp
30
frame pointer
$ra
31
return address
Register 1 ($at) is reserved for the assembler, 26-27 ($k0, $k1) for operating system. Registers 28-31 ($gp, $sp, $fp, $ra) are reserved for special uses, not user variables.
Policy of Use Conventions MIPS Assembly 15
CS@VT Computer Organization II ý2005-2015 McQuain
You may have noticed something is odd about a number of the MIPS instructions that have been covered so far. For example:
li $t0, 0xFFFFFFFF
Now, logically there's nothing wrong with wanting to place a 32-bit value into one of the
registers.
But there's certainly no way the instruction above could be translated into a 32-bit machine instruction, since the immediate value alone would require 32 bits.
This is an example of a pseudo-instruction. A MIPS assembler, or SPIM, may be designed to support such extensions that make it easier to write complex programs.
In effect, the assembler supports an extended MIPS architecture that is more sophisticated than the actual MIPS architecture of the underlying hardware.
Of course, the assembler must be able to translate every pseudo-instruction into a sequence of valid MIPS assembly instructions.
Pseudo-Instructions MIPS Assembly 16
CS@VT Computer Organization II ý2005-2015 McQuain
Basic fact: at the machine language level there are no explicit data types, only contents of memory locations. The concept of type is present only implicitly in how data is used.
declaration: reserving space in memory, or deciding that a certain data item will reside in a certain register.
Directives are used to reserve or initialize memory:
.data
.asciiz "a string" .byte 13, 14, -3 .space 16
.word 13, 14, -3
# mark beginning of a data segment
# declare and initialize a string
# store values in successive bytes
# alloc 16 bytes of space
# store values in successive words
A complete listing of MIPS/MARS directives can be found in the MARS help feature.
Data MIPS Assembly 17
CS@VT Computer Organization II ý2005-2015 McQuain
First step is to reserve sufficient space for the array.
Array elements are accessed via their addresses in memory, which is convenient if you¡¯ve given the .space directive a suitable label.
list: size: ...
.data
.word 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 .word 10
la $t1, list # get array address
li $t2, 0 # set loop counter
print_loop:
beq $t2, $t3, print_loop_end # check for array end
lw $a0, ($t1) # print value at the array pointer li $v0, 1
syscall
addi $t2, $t2, 1 # advance loop counter addi $t1, $t1, 4 # advance array pointer j print_loop # repeat the loop
print_loop_end:
Arrays MIPS Assembly 18
CS@VT Computer Organization II ý2005-2015 McQuain
This is part of the palindrome example from the course website:
.data string_space: .space 1024
...
# prior to the loop, $t1 is set to the address of the first # char in string_space, and $t2 is set to the last one test_loop:
...
bge $t1, $t2, is_palin
lb $t3, ($t1)
lb $t4, ($t2)
bne $t3, $t4, not_palin
addu $t1, $t1, 1
subu $t2, $t2, 1
j test_loop
# if lower pointer >= upper
# pointer, yes
# grab the char at lower ptr # grab the char at upper ptr # if different, it’s not
# advance lower ptr
# advance upper ptr
# repeat the loop
Array Example MIPS Assembly 19
CS@VT Computer Organization II ý2005-2015 McQuain
From previous study of high-level languages, we know the basic issues: – declaration: header, body, local variables
– call and return
– parameters of various types, with or without type checking, and a return value
– nesting and recursion
At the machine language level, there is generally little if any explicit support for procedures. This is especially true for RISC architectures.
There are, however, many conventions at the assembly language level.
Procedure Support MIPS Assembly 20
CS@VT Computer Organization II ý2005-2015 McQuain
Calling a procedure requires transferring execution to a different part of the code… in other words, a branch or jump operation:
jal
# PC = MIPS reserves register $31, aka $ra, to store the return address.
The called procedure must place the return value (if any) somewhere from which the
caller can retrieve it. The convention is that registers $v0 and $v1 can be used to hold the return value. We will discuss what to do if the return value exceeds 4 bytes later…
Returning from the procedure requires transferring execution to the return address the jal instruction placed in $ra:
jr $ra # PC = $ra
Procedure Call and Return MIPS Assembly 21
CS@VT Computer Organization II ý2005-2015 McQuain
In most cases, passing parameters is straightforward, following the MIPS convention:
$a0 # 1st parameter
$a1 # 2nd parameter
$a2 # 3rd parameter
$a3 # 4th parameter
The called procedure can then access the parameters by following the same convention.
What if a parameter needs to be passed by reference? Simply place the address of the relevant data object in the appropriate register, and design the called procedure to treat that register value accordingly.
What if a parameter is smaller than a word? Clever register manipulation in the callee. What if there are more than four parameters? We’ll discuss that later…
Passing Parameters MIPS Assembly 22
CS@VT Computer Organization II ý2005-2015 McQuain
Let’s implement a MIPS procedure to get a single integer input value from the user and return it:
get_integer:
# Prompt the user to enter an integer value. Read and return # it. It takes no parameters.
li $v0, 4
la $a0, prompt
syscall
li $v0, 5 syscall
jr $ra
# # # # # #
system call code for printing a string = 4
address of string is argument 0 to
print_string
call operating system to perform
print operation
# get ready to read in integers
# system waits for input, puts the # value in $v0
Since this doesn’t use any registers that it needs to save, there’s no involvement with the run-time stack.
Procedure Example 1 MIPS Assembly 23
CS@VT Computer Organization II ý2005-2015 McQuain
Since the procedure does not take any parameters, the call is simple. The return value will, by convention, have been placed in $v0.
…
main:
move
get_integer $s0, $v0
…
.data # Data declaration section
prompt: .asciiz “Enter an integer value\n”
.text jal
# Start of code section
# Call procedure
# Put returned value in “save” reg
Procedure Call Example 1 MIPS Assembly 24
CS@VT Computer Organization II ý2005-2015 McQuain
In addition to memory for static data and the program text (machine code), MIPS provides space for the run-time stack (data local to procedures, etc.) and for dynamically-allocated data:
$sp # last word alloc on stack
Stack
Dynamic data
Static data
Text
Reserved
$gp # ptr into global data
$pc # ptr to next instruction
Dynamic data is accessed via pointers held by the program being executed, with addresses returned by the memory allocator in the underlying operating system.
MIPS Memory Organization MIPS Assembly 25
CS@VT Computer Organization II ý2005-2015 McQuain
MIPS provides a special register, $sp, which holds the address of the most recently allocated word on a stack that user programs can employ to hold various values:
Note that the run-time stack is “upside-down”. That is, $sp, decreases when a value is added to the stack and increases when a value is removed.
So, you decrement the stack pointer by 4 when pushing a new value onto the stack and increment it by 4 when popping a value off of the stack.
The System Stack MIPS Assembly 26
CS@VT Computer Organization II ý2005-2015 McQuain
MIPS programs use the runtime stack to hold:
– “extra” parameters to be passed to a called procedure
– register values that need to be preserved during the execution of a called procedure and restored after the return
– saved procedure return address, if necessary
– local arrays and structures, if any
activation record or stack frame for called procedure
Using the System Stack MIPS Assembly 27
CS@VT Computer Organization II ý2005-2015 McQuain
By convention, the caller will use:
– registers $s0 – $s7 for values it expects to be preserved across any procedure calls
it makes
– registers $t0 – $t9 for values it does not expect to be preserved
It is the responsibility of the called procedure to make sure that if it uses any of the registers $s0 – $s7 it backs them up on the system stack first, and restores them before
returning.
Obviously, the called procedure also takes responsibility to:
– allocate any needed space on the stack for local data
– place the return value onto the stack
In some situations, it is useful for the caller to also maintain the value that $sp held when the call was made, called the frame pointer. The register $fp would be used for this purpose.
System Stack Conventions MIPS Assembly 28
CS@VT Computer Organization II ý2005-2015 McQuain