CA Lec4 Chap2 MIPS Instructions 3
CA Lec4 Chap2 MIPS Instructions 3
CA Lec4 Chap2 MIPS Instructions 3
2
Korea Univ
Why Branch?
• An advantage of a computer over a calculator is its ability to make
decisions
A computer performs different tasks depending on conditions
In high-level language, if/else, case, while and for loops
statements all conditionally execute code
3
Korea Univ
Branch Instructions in MIPS
4
Korea Univ
beq, bne
• I format instruction
beq (bne) rs, rt, label
• Examples:
bne $s0, $s1, skip // go to “skip” if $s0$s1
beq $s0, $s1, skip // go to “skip” if $s0==$s1
…
skip: add $t0, $t1, $t2
opcode rs rt immediate
4 16 17 ?
32 Branch
Add
PC + 4 32 destination
32 address
32
6
Korea Univ
bne Example
Notice that the assembly tests for the opposite case (i != j),
as opposed to the test in the high-level code (i == j).
7
Korea Univ
In Support of Branch
• There are 4 instructions (slt, sltu, slti, sltiu)that help you set the conditions
slt, slti for signed numbers
sltu, sltiu for unsigned numbers
• Instruction format
slt rd, rs, rt // Set on less than (R format)
sltu rd, rs, rt // Set on less than unsigned (R format)
slti rt, rs, imm // Set on less than immediate (I format)
sltiu rt, rs, imm // Set on less than unsigned immediate (I format)
Name Register
• Examples: Number
8
Korea Univ
Branch Pseudo Instructions
• blt, ble, bgt and bge are pseudo instructions for signed number
comparison
The assembler uses a reserved register ($at) when expanding the pseudo instructions
MIPS compilers use slt, slti, beq, bne and the fixed value of 0 (always available
by reading the register $zero) to create all relative conditions (equal, not equal, less
than, less than or equal, greater than, greater than or equal)
• bltu, bleu, bgtu and bgeu are pseudo instructions for unsigned
number comparison
9
Korea Univ
Bounds Check Shortcut
• Treating signed numbers as if they were unsigned gives a low cost way
of checking if 0 ≤ x < y (index out of bounds for arrays)
The key is that negative integers in two’s complement look like large numbers
in unsigned notation.
Thus, an unsigned comparison of x < y also checks if x is negative as well
as if x is less than y
int my_array[100] ;
// $t2 = 100
// $s1 has a index to the array and changes dynamically while executing the program
// $s1 and $t2 contain signed numbers, but the following code treats them as
unsigned numbers
sltu $t0, $s1, $t2 # $t0 = 0 if $s1 >= 100 (=$t2) or $s1 < 0
beq $t0, $zero, IOOB # go to IOOB if $t0 = 0
10
Korea Univ
j, jr, jal
• Example
j LLL
…….
LLL:
2 ?
11
Korea Univ
Branching Far Away
12
Korea Univ
While in C
Notice that the assembly tests for the opposite case (pow ==
128) than the test in the high-level code (pow != 128).
13
Korea Univ
for in C
Notice that the assembly tests for the opposite case (i == 10)
than the test in the high-level code (i != 10).
14
Korea Univ
Comparisons in C
15
Korea Univ
Procedure (Function)
16
Korea Univ
jal
• Procedure call instruction (J format)
jal ProcedureAddress # jump and link
# $ra <- pc + 4
# pc <- jump target
• jal saves PC+4 in the register $ra to return from the procedure
3 26-bit address
High-level code
MIPS assembly code
PC
int main() {
simple(); 0x00400200 main: jal simple
a = b + c; compile
0x00400204 add $s0, $s1, $s2
}
...
PC+4
void simple() {
return; 0x00401020 simple: jr $ra
}
jal: jumps to simple and saves PC+4 in the return address register
void means that simple doesn’t return a value. ($ra). In this case, $ra = 0x00400204 after jal executes
17
Korea Univ
jr
0 31 8
High-level code
MIPS assembly code
int main() {
simple(); 0x00400200 main: jal simple
a = b + c; compile
0x00400204 add $s0, $s1, $s2
}
...
void simple() {
return; 0x00401020 simple: jr $ra
}
$ra contains 0x00400204
jr $ra: jumps to address in $ra (in this case 0x00400204)
18
Korea Univ
Procedure Call Conventions
• MIPS conventions
jal calls a procedure
• Arguments are passed via $a0, $a1, $a2, $a3
jr returns from the procedure
• Return results are stored in $v0 and $v1
19
Korea Univ
Arguments and Return Values
MIPS assembly code
20
Korea Univ
Register Corruption
High-level code MIPS assembly code
# $s0 = y
int main()
{ main:
int a, b, c; ...
int y; addi $t0, $0, 1 # a = 1
addi $t1, $0, 2 # b = 2
a = 1;
b = 2; addi $a0, $0, 2 # argument 0 = 2
addi $a1, $0, 3 # argument 1 = 3
// 4 arguments addi $a2, $0, 4 # argument 2 = 4
y = diffofsums(2, 3, 4, 5); addi $a3, $0, 5 # argument 3 = 5
jal diffofsums # call procedure
c = a + b; add $s0, $v0, $0 # y = returned value
printf(“y = %d, c = %d”, y, c)
} add $s1, $t0, $t1 # a = b + c
...
int diffofsums(int f, int g, int h, int i)
{ # $s0 = result
int result; diffofsums:
result = (f + g) - (h + i); add $t0, $a0, $a1 # $t0 = f + g
return result; // return value add $t1, $a2, $a3 # $t1 = h + i
} sub $s0, $t0, $t1 # result =(f + g)-(h + i)
add $v0, $s0, $0 # put return value in $v0
jr $ra # return to caller
• We need a place to temporarily
store registers
21
Korea Univ
The Stack
• CPU has only a limited number of
registers (32 in MIPS), so it typically
can not accommodate all the
variables you use in the code
So, programmers (or compiler) use the
stack for backing up the registers and
restoring those when needed
22
Korea Univ
The Stack - Spilling Registers
23
Korea Univ
Example (Problem)
• Called procedures (callees) MIPS assembly code
must not have any
# $s0 = y
unintended side effects to
the caller main:
...
addi $a0, $0, 2 # argument 0 = 2
addi $a1, $0, 3 # argument 1 = 3
• diffofsums uses addi $a2, $0, 4 # argument 2 = 4
(overwrites) 3 registers addi
jal
$a3, $0, 5
diffofsums
#
#
argument 3 = 5
call procedure
($t0, $t1, $s0) add $s0, $v0, $0 # y = returned value
...
# $s0 = result
diffofsums:
add $t0, $a0, $a1 # $t0 = f + g
add $t1, $a2, $a3 # $t1 = h + i
sub $s0, $t0, $t1 # result =(f + g)-(h + i)
add $v0, $s0, $0 # put return value in $v0
jr $ra # return to caller
24
Korea Univ
Example (Solution with Stack)
# $s0 = result
diffofsums:
“Push” (back up) the
addi $sp, $sp, -12 # make space on stack
registers to be used in the
# to store 3 registers
sw $s0, 8($sp) # save $s0 on stack callee to the stack
sw $t0, 4($sp) # save $t0 on stack
sw $t1, 0($sp) # save $t1 on stack
add $t0, $a0, $a1 # $t0 = f + g
add $t1, $a2, $a3 # $t1 = h + i
sub $s0, $t0, $t1 # result = (f + g) - (h + i)
add $v0, $s0, $0 # put return value in $v0 “Pop” (restore) the registers
lw $t1, 0($sp) # restore $t1 from stack from the stack prior to
lw $t0, 4($sp) # restore $t0 from stack returning to the caller
lw $s0, 8($sp) # restore $s0 from stack
addi $sp, $sp, 12 # deallocate stack space
jr $ra # return to caller
FC ? $sp FC ? FC ? $sp
stack frame
F8 F8 $s0 F8
F4 F4 $t0 F4
F0 F0 $t1 $sp F0
proc1:
addi $sp, $sp, -4 # make space on stack
sw $ra, 0($sp) # save $ra on stack
jal proc2
...
lw $ra, 0($sp) # restore $s0 from stack
addi $sp, $sp, 4 # deallocate stack space
jr $ra # return to caller
26
Korea Univ
Recursive Procedure Call
• Recursive procedures
MIPS assembly code
invoke clones of
themselves 0x90 factorial: addi $sp, $sp, -8 # make room
0x94 sw $a0, 4($sp) # store $a0
High-level code 0x98 sw $ra, 0($sp) # store $ra
0x9C addi $t0, $0, 2
int factorial(int n) { 0xA0 slt $t0, $a0, $t0 # a <= 1 ?
if (n <= 1) 0xA4 beq $t0, $0, else # no: go to else
return 1; 0xA8 addi $v0, $0, 1 # yes: return 1
else 0xAC addi $sp, $sp, 8 # restore $sp
return (n * factorial(n-1));
0xB0 jr $ra # return
}
0xB4 else: addi $a0, $a0, -1 # n = n - 1
0xB8 jal factorial # recursive call
0xBC lw $ra, 0($sp) # restore $ra
0xC0 lw $a0, 4($sp) # restore $a0
0xC4 addi $sp, $sp, 8 # restore $sp
0xC8 mul $v0, $a0, $v0 # n * factorial(n-1)
0xCC jr $ra # return
27
Korea Univ
Stack during Recursive Call (3!)
28
Korea Univ
Backup Slides
29
Korea Univ
Stack Example
int main()
int main() {
{ 400168: 27bdffd8 addiu sp,sp,-40
int a, b, c; // local variable: 40016c: afbe0020 sw s8,32(sp)
// allocated in stack 400170: 03a0f021 move s8,sp
int myarray[5]; // local variable: int a, b, c; // local variable: allocated in stack
// allocated in stack int myarray[5]; // local variable: allocated in stack
a = 2; a = 2;
b = 3;
compile 400174:
400178:
24020002
afc20008
li
sw
v0,2
v0,8(s8)
*(myarray+1) = a; b = 3;
*(myarray+3) = b; 40017c: 24020003 li v0,3
400180: afc20004 sw v0,4(s8)
c = myarray[1] + myarray[3];
*(myarray+1) = a;
return c; 400184: 27c2000c addiu v0,s8,12
} 400188: 24430004 addiu v1,v0,4
40018c: 8fc20008 lw v0,8(s8)
400190: 00000000 nop
400194: ac620000 sw v0,0(v1)
memory *(myarray+3) = b;
High address 400198: 27c2000c addiu v0,s8,12
40019c: 2443000c addiu v1,v0,12
4001a0: 8fc20004 lw v0,4(s8)
$sp 4001a4: 00000000 nop
36
32
stack 4001a8: ac620000 sw v0,0(v1)
s8
28 c = myarray[1] + myarray[3];
24 4001ac: 8fc30010 lw v1,16(s8)
myarray[3] = b 4001b0: 8fc20018 lw v0,24(s8)
20 4001b4: 00000000 nop
myarray[1] = a 16 4001b8: 00621021 addu v0,v1,v0
12 4001bc: afc20000 sw v0,0(s8)
a=2 8
return c;
b=3 4 4001c0: 8fc20000 lw v0,0(s8)
$s8 = $sp $sp = $sp - 40 c = my[1]+my[3] 0 }
4001c4: 03c0e821 move sp,s8
4001c8: 8fbe0020 lw s8,32(sp)
4001cc: 27bd0028 addiu sp,sp,40
heap 4001d0: 03e00008 jr ra
Low address 4001d4: 00000000 nop
30
Korea Univ
The MIPS Memory Map
• Addresses shown are only a software convention (not part Address Segment
of the MIPS architecture) 0xFFFFFFFC
0x00000000
31
Korea Univ
Linear Space Segmentation
32
Korea Univ
Stack Frame
33
Korea Univ
Frame Pointer
Code that needs to access a local variable within the current frame, or an argument near the top of the
calling frame, can do so by adding a predetermined offset to the value in the frame pointer.
34
Korea Univ
SP & FP
• The data stored in the stack frame may sometimes be
accessed directly via the stack pointer register (SP, which
indicates the current top of the stack).
-Wiki
35
Korea Univ
Stack Layout with x86
• In the previous example, if the calling procedure does not use the temporary registers ($t0,
$t1), the effort to save and restore them is wasted
• To avoid this waste, MIPS divides registers into preserved and non-preserved categories
• The preserved registers include $s0 ~ $s7 (saved)
• The non-preserved registers include $t0 ~ $t9 (temporary)
• So, a procedure must save and restore any of the preserved registers it wishes to use, but it can
change the non-preserved registers freely
• The callee must save and restore any preserved registers it wishes to use
• The callee may change any of the non-preserved registers
• But, if the caller is holding active data in a non-preserved register, the caller needs
to save and restore it
Preserved Non-preserved
(Callee-saved) (Caller-saved)
$s0 - $s7 $t0 - $t9
$ra $a0 - $a3
$sp $v0 - $v1
stack above $sp stack below $sp
37
Korea Univ
Storing Saved Registers on the Stack
# $s0 = result
diffofsums:
addi $sp, $sp, -4 # make space on stack to
# store one register
sw $s0, 0($sp) # save $s0 on stack
# no need to save $t0 or $t1
add $t0, $a0, $a1 # $t0 = f + g
add $t1, $a2, $a3 # $t1 = h + i
sub $s0, $t0, $t1 # result = (f + g) - (h + i)
add $v0, $s0, $0 # put return value in $v0
lw $s0, 0($sp) # restore $s0 from stack
addi $sp, $sp, 4 # deallocate stack space
jr $ra # return to caller
38
Korea Univ