Data types:
Literals:
ex: A template for a MIPS assembly language program
# Comment giving name of program and description of function
# Template.s
# Bare-bones outline of MIPS assembly language program
.data
# variable declarations here
# ...
.text
__start: # indicates start of code (first instruction to execute)
# remainder of program code here
# ...
# ...
done # indicates program end
format for declarations:
name: storage_type value(s)
example
var1: .word 3 # create a single integer variable with initial value 3
array1: .byte 'a','b' # create a 2-element character array with elements initialized
# to a and b
array2: .space 40 # allocate 40 consecutive bytes, with storage uninitialized
# could be used as a 40-element character array, or a
# 10-element integer array; a comment should indicate which!
load:
lw register_destination, RAM_source
lb register_destination, RAM_source
sw register_source, RAM_destination
sb register_source, RAM_destination
li register_destination, value
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)
sw $t2, ($t0)
based or indexed addressing:
lw $t2, 4($t0)
sw $t2, -12($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
add $t0,$t1,$t2 # $t0 = $t1 + $t2; add as signed (2's complement) integers
sub $t2,$t3,$t4 # $t2 = $t3 Ð $t4
addi $t2,$t3, 5 # $t2 = $t3 + 5; "add immediate" (no sub immediate)
addu $t1,$t6,$t7 # $t1 = $t6 + $t7; add as unsigned integers
subu $t1,$t6,$t7 # $t1 = $t6 + $t7; subtract as unsigned integers
mult $t3,$t4 # multiply 32-bit quantities in $t3 and $t4, and store 64-bit
# result in special registers Lo and Hi: (Hi,Lo) = $t3 * $t4
div $t5,$t6 # Lo = $t5 / $t6 (integer quotient)
# Hi = $t5 mod $t6 (remainder)
mfhi $t0 # move quantity in special register Hi to $t0: $t0 = Hi
mflo $t1 # move quantity in special register Lo to $t1: $t1 = Lo
# used to get at result of product or quotient
move $t2,$t3 # $t2 = $t3
Branches
b target # unconditional branch to program label target
beq $t0,$t1,target # branch to target if $t0 = $t1
blt $t0,$t1,target # branch to target if $t0 < $t1
ble $t0,$t1,target # branch to target if $t0 <= $t1
bgt $t0,$t1,target # branch to target if $t0 > $t1
bge $t0,$t1,target # branch to target if $t0 >= $t1
bne $t0,$t1,target # branch to target if $t0 <> $t1
Jumps
j target # unconditional jump to program label target
jr $t3 # jump to address contained in $t3 ("jump register")
Subroutine Calls
subroutine call: "jump and link" instruction
jal sub_label # "jump and link"
jr $ra # "jump register"
Note: return address stored in register $ra; if subroutine will call other subroutines, or is recursive, return address should be copied from $ra onto stack to preserve it, since jal always places return address in this register and hence will overwrite previous value
ex Print out integer value contained in register $t2 li $v0, 1 # load appropriate system call code into register $v0; # code for printing integer is 1 move $a0, $t2 # move integer to be printed into $a0: $a0 = $t2 syscall # call operating system to perform operation ex Read integer value, store in RAM location with label int_value (presumably declared in data section) li $v0, 5 # load appropriate system call code into register $v0; # code for reading integer is 5 syscall # call operating system to perform operation sw $a0, int_value # value read from keyboard returned in register $a0; # store this in desired location ex Print out string (useful for prompts) .data string1 .asciiz "Print this.\n" # declaration for string variable .text main: li $v0, 4 # load appropriate system call code into register $v0; # code for printing string is 4 la $a0, string1 # load address of string to be printed into $a0 syscall # call operating system to perform print operation Note:
Example 1
# Compute the value of the sum 1*2 + 2*3 + 3*4 + ... + 10*11, and store in register $t1
.data # variable declaration section
out_string: .asciiz "The result is:\n" # declares a null-terminated string, to "prettify" output
.text
__start: # indicates start of code
li $t0, 1 # $t0 will be a counter; initialize to 1
li $t1, 0 # $t1 will hold the sum
li $t2, 10 # $t2 will hold loop limit
loop_top: bgt $t0,$t2,loop_end # exit loop if $t0 > 10
addi $t3,$t0,1 # $t3 = $t0 + 1
mult $t0,$t3 # special register Lo = $t0 * $t3
# (don't need Hi since values are small)
mflo $t3 # $t3 = Lo (= $t0 * $t3)
add $t1,$t1,$t3 # $t1 = $t1 + $t3
addi $t0, 1 # increment counter
b loop_top # branch to loop_top
loop_end: puts out_string # print out the result string
puti $t1 # print out integer value in $t1
done # carriage return at the end of this line to keep SPIM happy!
Example 2
# Code with subroutine to compute Fibonacci number recursively
# Uses system stack
.data
in_string: .asciiz "Input a positive integer:\n"
out_string: .asciiz "The Fibonacci number is:\n"
.text
__start:
puts in_string # print out prompt
geti $s0 # read integer into $s0
sw $s0,($sp) # push argument for Fib on stack
addi $sp,$sp,-4 # and decrement stack pointer
jal Fib # jump to subroutine
addi $sp,$sp,4 # increment stack pointer
lw $s1,($sp) # and pop result from stack
puts out_string # print out prompt
puti $s1 # print out result
done
##################################################################################
# Fibonacci subroutine
# input: integer n, on stack
# output: Fib(n), nth Fibonacci number
# description: recursively computes Fib(n) = Fib(n-1) + Fib(n-2), Fib(1) = Fib(2) = 1.
# uses: $t0, $t1
##################################################################################
Fib:
# procedure prologue:
sw $ra,($sp) # save return address on stack, since recursive,
addi $sp,$sp,-4 # and decrement stack pointer
sw $fp,($sp) # save previous frame pointer on stack
addi $sp,$sp,-4 # and decrement stack pointer
add $fp,$sp,12 # set frame pointer to point at base of stack frame
lw $t0,($fp) # copy argument to $t0: $t0 = n
li $t1, 2
bgt $t0,$t1,do_recurse # if argument n >= 2, branch to recursive sequence
li $t0, 1 # else set result to 1 (base cases n = 1 and n = 2)
b epilogue # branch to end
do_recurse: addi $t0,$t0,-1 # $t0 = n-1
sw $t0,($sp) # push argument n-1 on stack
addi $sp,$sp,-4 # and decrement stack pointer
jal Fib # call Fibonacci with argument n-1
# leave result on stack for now
lw $t0,($fp) # re-copy argument to $t0: $t0 = n
addi $t0,$t0,-2 # $t0 = n-2
sw $t0,($sp) # push argument n-2 on stack
addi $sp,$sp,-4 # and decrement stack pointer
jal Fib # call Fibonacci with argument n-2
addi $sp,$sp,4 # increment stack pointer
lw $t0,($sp) # and pop result of Fib(n-2) from stack into $t0
addi $sp,$sp,4 # increment stack pointer
lw $t1,($sp) # and pop result of Fib(n-1) from stack into $t1
add $t0,$t0,$t1 # $t0 = Fib(n-2) + Fib(n-1); have result
epilogue: # procedure epilogue: $t0 holds result
addi $sp,$sp,4 # increment stack pointer
lw $fp,($sp) # and pop saved frame pointer into $fp
addi $sp,$sp,4 # increment stack pointer
lw $ra,($sp) # and pop return address into $ra
addi $sp,$sp,4 # increment stack pointer
# to pop argument (n) from stack (discard)
sw $t0,($sp) # push result onto stack
addi $sp,$sp,-4 # and decrement stack pointer
jr $ra # return to caller
##################################################################################
# end of Fibonacci
##################################################################################
Jonathan Sevy, https://jsevy.com
Comments? jsevy@jsevy.com