Professional Documents
Culture Documents
MIPS
Assembly Language
Programming (2)
Basic Instructions
Manipulate data:
ADD SUB MUL DIV AND OR XOR ADDI SLL
Memory Instruction:
LW SW LB SB
Branches
J BNE BEQ BGE
2
Decisions: C if Statements
2 kinds of if statements in C
if (condition) statement-block if (condition) statement-block1 else statement-block2
MIPS code:
beq $s3,$s4,True sub $s0,$s1,$s2 j Fin True: add $s0,$s1,$s2 Fin:
Loops in C/Assembly
There are three types of loops in C:
dowhile while for
Case-Switch Statement
C code switch(k) { case 0: f = i + j; break; case 1: f = g + h; break; case 2: f = g - h; break; case 3: f = i - j; break; } Can be rewritten as if (k == 0) f = i + j; else if (k == 1) f = g + h; else if (k == 2) f = g h; else if (k == 3) f = i j;
Procedure
What is procedure?
Example Code
main() { int a, b; sum(a,b); } int sum(int x, int y) { return(x+y); } Steps: 1. Caller places parameters in a place where the procedure can access them 2. Transfer control to the procedure 3. Acquire storage resources required by the procedure 4. Execute the statements in the procedure 5. Called function places the result in a place where the caller can access it 6. Return control to the statement next to the procedure call
main:
sum:
add $a0,$s0,$zero add $a1,$s1,$zero addi $ra,$zero,? j sum ... add $v0,$a0,$a1 jr $ra
# new instruction
In MIPS, all instructions are 4 bytes, and stored in memory just like data.
main:
sum:
add $a0,$s0,$zero add $a1,$s1,$zero addi $ra,$zero,? j sum ... add $v0,$a0,$a1 jr $ra
# new instruction
main:
sum:
add $a0,$s0,$zero add $a1,$s1,$zero addi $ra,$zero,1016 j sum ... add $v0,$a0,$a1 jr $ra
# new instruction
MIPS provides a single instruction called jal to 1. Load $ra with addr of next instruction 2. Jump to the procedure.
main:
sum:
add $a0,$s0,$zero add $a1,$s1,$zero jal sum ... add $v0,$a0,$a1 jr $ra
Non-Leaf Procedures
main() { int a, b; sum2(a,b); } int sum2(int x, int y) { return(sum(x,x) + y); } 1000 1004 1008 main: add $a0,$s0,$zero add $a1,$s1,$zero jal sum2 ...
sum2: add $a1,$a0,$0 jal sum add $v0, $v0, $a1 jr $ra sum: add $v0, $a0, $a1 jr $ra
main:
$a0 a
$a1
$v0
...
2000 2004 2008 2012 4000 4004 sum2: add $a1,$a0,$0 jal sum add $v0, $v0, $a1 jr $ra add $v0, $a0, $a1 jr $ra
1008
2000 2004 4000 4004
1012
a 2008 a+a
sum:
2008
2012 2008
a+a+a
a+a+a+a
We need to do some bookkeeping! We need to save registers before rewriting them. Where should we save them?
Memory Organization
$sp
Reserved
Stack
0x80000000
0x10040000
0x10000000
Text
To push a word on stack, decrement $sp by 4, and use sw To pop a word from stack, increment $sp by 4
Reserved
0x00400000
Saving registers
Following registers should be spilled to the stack
$ra ($31) $a0-$a3 ($4-$7) $t0-$t7 ($8-$15) $s0-$s7 ($16-$23) $fp ($30)
Saved by caller on stack before jal and restored after returning from jal; done only for registers used after jal Saved by called procedure before rewriting and then restored back before returning
main:
$a0 a
$a1
$v0
...
2000 2004 2008 2012 4000 4004 sum2: add $a1,$a0,$0 jal sum add $v0, $v0, $a1 jr $ra add $v0, $a0, $a1 jr $ra
1008
2000 2004 4000 4004
1012
a 2008 a+a
sum:
2008
2012 2008
a+a+a
a+a+a+a
1000
add $a1,$s1,$zero addi $sp, $sp, -4 sw $ra, 0($sp) jal sum2 lw $ra, 0($sp) addi $sp, $sp, 4 jr $ra
sum2: addi $sp, $sp, -8 sw $ra, 4($sp) sw $a1, 0($sp) add $a1,$a0,$0 jal sum lw $a1, 0($sp) lw $ra, 4($sp) add $sp, $sp, 8 add $v0, $v0, $a1 jr $ra sum: add $v0, $a0, $a1 jr $ra
Addr 1000 1004 1008 1012 1016 2000 2004 2008 2012 2016 4000 4004 2020 2024 2028 2032 2036 1020 1024 1028
$sp=x $sp
$sp y
1020
$sp b
Recursive functions
main() { fact(2); } 1000 1004 1008 1012 1016 1020 1024 2000 2004 2008 2012 2016 2020 2024 2028 2032 2036 2040 2044 2048 2052 main: addi $a0, $0, 2 addi $sp, $sp, -4 sw $ra, 0($sp) jal fact lw $ra 0($sp) addi $sp, $sp, 4 jr $ra slti $t0, $a0, 1 beq $t0, $0, L1 addi $v0, $0, 1 jr $ra addi $sp, $sp, -8 sw $ra, 4($sp) sw $a0, 0($sp) addi $a0, $a0, -1 jal fact lw $a0, 0($sp) lw $ra, 4($sp) add $sp, $sp, 8 mul $v0, $a0, $v0 jr $ra
fact:
L1:
1000 main: addi $a0, $0, 2 1004 addi $sp, $sp, -4 1008 sw $ra, 0($sp) 1012 jal fact 1016 lw $ra 0($sp) 1020 addi $sp, $sp, 4 1024 jr $ra 2000 fact: slti $t0, $a0, 1 2004 beq $t0, $0, L1 2008 addi $v0, $0, 1 2012 jr $ra 2016 L1: addi $sp, $sp, -8 2020 sw $ra, 4($sp) 2024 sw $a0, 0($sp) 2028 addi $a0, $a0, -1 2032 jal fact 2036 lw $a0, 0($sp) 2040 lw $ra, 4($sp) 2044 add $sp, $sp, 8 2048 mul $v0, $a0, $v0 2052 jr $ra
Addr $ra=y $a0 1000 2 1004 1008 1012 1016 2000 2004 2016 2020 2024 2028 1 2032 2036 2000 2004 2016 2020 2024 2028 0 2032 2036 2000 2004 2008 2012 2036 1 2040 2036 2044 2048 2052 2036 2 2040 1016 2044
$t0
$sp
4 bytes
hi $sp y
1016
0 x-12
$sp 2
2036
$sp 1
0
lo
x-20
1 1
x-12 1
x-4
Argument Passing
Recall: arguments to a procedure passed through $a0-$a3 What if the procedure has > 4 arguments?
First four arguments are put in $a0-$a3 Remaining arguments are put on stack by the caller
hi
x7 x6 x5
$sp x4
lo
Return Values
Recall: return values from a procedure passed through $v0-$v1 What if the procedure has > 2 return values?
First two return values put in $v0-$v1 Remaining return values put on stack by the procedure The remaining return values are popped from the stack by the caller
Variables
Memory for Global variables is allocated using assembler directives like .space, .word, .halfword, .byte, etc. Memory allocated is in the static data portion if MIPS memory What about local variables?
stuff[2]
stuff[1] stuff[0] n m l
$sp k
24 20 16
12
8 4 0
stuff[2]
stuff[1] stuff[0] n m l
$sp k
24 20 16
12
8 4 0
$sp $t0
Frame Pointers
Use register $30 ($fp) At entry the called procedure
Saves old $fp on stack sets $fp = $sp 4
Hi addr
$sp
0 -4
stuff[2] stuff[1]
-8
-12 -16 -20 -24 -28
stuff[0] n m l
$sp k
$sp $t0
Before return
Set $sp = $fp + 4 Restore old $fp value from stack and set $fp = old $fp
Lo addr