computer organization cs224 fall 2012 lessons 9 and 10
TRANSCRIPT
Computer OrganizationCS224
Fall 2012
Lessons 9 and 10
MIPS procedure call instruction:
jal ProcedureAddress #jump and link
Saves PC+4 in register $ra to have a link to the next instruction, for the procedure return; jumps to target addr.
Machine format (J format):
Procedure return copies return address to PC:
jr $ra #return to callpoint+4;
Instruction format (R format):
Instructions for Accessing Procedures
0x03 26 bit address
0 31 0x08
§2.8 Supporting P
rocedures in Com
puter Hardw
are
Six Steps in Execution of a Procedure1. Main routine (caller) places parameters in a place
where the procedure (callee) can access them $a0 - $a3: four argument registers
2. Caller transfers control to the callee (jal Dest)
3. Callee acquires the storage resources needed
4. Callee performs the desired task
5. Callee places the result value in a place where the caller can access it $v0 - $v1: two value registers for result values
6. Callee returns control to the caller (jr $ra) $ra: one return address register to return to the point of origin
Register Usage $a0 – $a3: arguments (reg’s 4 – 7)
$v0, $v1: result values (reg’s 2 and 3)
$t0 – $t9: temporaries (reg’s 8-15, 24-25) Can be overwritten by callee
$s0 – $s7: saved (reg’s 16-23) Must be saved/restored by callee !
$gp: global pointer for static data (reg 28)
$sp: stack pointer (reg 29)
$fp: frame pointer (reg 30)
$ra: return address (reg 31)
$gp, $sp, $fp, $ra must be saved/restored by callee !
MIPS Register ConventionName Register
NumberUsage Preserve
on call?$zero 0 constant 0 (hardware) n.a.
$at 1 reserved for assembler n.a.
$v0 - $v1 2-3 returned values no
$a0 - $a3 4-7 arguments no
$t0 - $t7 8-15 temporaries no
$s0 - $s7 16-23 saved values yes
$t8 - $t9 24-25 temporaries no
$k0 - $k1 26-27 reserved for op system n.a.
$gp 28 global pointer yes
$sp 29 stack pointer yes
$fp 30 frame pointer yes
$ra 31 return addr (hardware) yes
Stack Usage Both caller and callee use a stack – a last-in-first-out
queue
low addr
high addr
$sp
One of the general registers, $sp ($29), is used to address the stack (which “grows” down, from high address to low address)
add data onto the stack – push
$sp = $sp – 4 put data on stack at new $sp
remove data from the stack – pop
get data from stack at $sp $sp = $sp + 4
top of stack
Leaf Procedure Example
C code:
int leaf_example (int g, h, i, j){ int f; f = (g + h) - (i + j); return f;}
Arguments g, …, j in $a0, …, $a3 f in $s0 (hence, need to save $s0 on stack) Return result in $v0
Leaf Procedure Example
MIPS code:
leaf_example: addi $sp, $sp, -4 sw $s0, 0($sp)
add $t0, $a0, $a1 add $t1, $a2, $a3 sub $s0, $t0, $t1
add $v0, $s0, $zero
lw $s0, 0($sp) addi $sp, $sp, 4
jr $ra
Note: it can be done in 4 lines (2 add, sub, jr) if $s0 is not used
Save $s0 on stack
Procedure body
Restore $s0
Result to$v0 for return
Return
Stacking of Subroutine Environments Procedures are often nested, there are multiple calls and returns
C is a “leaf” procedure, but B is a nested (non-leaf) procedure
The stack grows downward at each new call, shrinks upward at each return
A:A
CALL B
B: AB
CALL C ABC
C:
RET
RET
AB
A
Non-Leaf Procedures
Procedures that call other procedures
For nested call, caller needs to save on the stack: Its return address Any arguments and temporaries it still needs after the call
(which are not in saved registers)
Restore from the stack after the call
As with leaf procedures, callee also needs to save on the stack any “saved” registers, & restore them at end
Non-Leaf Procedure Example
C code:
int fact(int n){ if (n < 1) return (1); else return n * fact(n - 1);}
Argument n in $a0 Return result in $v0
Non-Leaf Procedure Example
MIPS code:
fact: addi $sp, $sp, -8 # adjust stack for 2 items sw $ra, 4($sp) # save return address sw $a0, 0($sp) # save argument
slti $t0, $a0, 1 # test for n < 1 beq $t0, $zero, L1 addi $v0, $zero, 1 # if so, result is 1 addi $sp, $sp, 8 # pop 2 items from stack jr $ra # and return
L1: addi $a0, $a0, -1 # else decrement n jal fact # recursive call
lw $a0, 0($sp) # restore original n lw $ra, 4($sp) # and return address addi $sp, $sp, 8 # pop 2 items from stack mul $v0, $a0, $v0 # multiply to get result jr $ra # and return
Local Data on the Stack
Local data allocated by callee e.g., C automatic variables
Procedure frame (aka activation record) Used by some compilers to manage stack storage
The frame pointer ($fp) points to the first word of the frame of a procedure – providing a stable “base” register for the procedure
Using Registers to Implement Procedures
Caller Save caller-saved registers $a0-$a3, $t0-$t9 (if their values need
preserving) Load arguments in $a0-$a3 (rest on stack above $fp) Execute jal instruction
Callee Setup Step 1: Allocate memory in frame ($sp = $sp - frame) Step 2: Save callee-saved registers $s0-$s7, $fp, $ra (if their values
will be changed) Step 3: Create frame ($fp = $sp + frame size - 4)
Callee Return Place return value in $v0 and $v1 Restore any callee-saved registers ($fp, $ra,$s0-$s7…) Pop stack ($sp = $sp + frame size) Return using jr $ra
Calling Convention: Steps
FP
SP
raold FP
$s0-$s7
FP
SP
First four arguments passed in registersBefore call:
Calleesetup; step 1
FPSPCallee
setup; step 2
raold FP
$s0-$s7
FPSPCallee
setup; step 3
Adjust SP
Save registers as needed
Adjust FP
Memory Layout Text: program code
Static data: global variables e.g., static variables in C, constant
arrays and strings $gp is initialized to address
10008000, allowing +/- offsets into this segment
Dynamic data: heap For structures that grow and shrink,
e.g. linked lists, trees, etc Allocate using malloc in C, (new in
Java); free it with free in C (automatic garbage collection in Java)
Stack: storage of automatic variables (local to a procedure)
Character Data
Byte-encoded character sets ASCII: 128 characters (= 7-bit)
- 95 graphic (i.e printable), 33 control Latin-1: 256 characters (= 8-bit)
- ASCII, +96 more graphic characters
Unicode: universal character set Used in Java, C++ wide characters, … Most of the world’s alphabets, plus symbols UTF-16 is the default (16-bit encoding for each character) UTF-32 is 32-bits per character UTF-8 is variable length: 8-bits to handle ASCII, plus 16-32 bits
for other characters
§2.9 Com
municating w
ith People
Byte/Halfword Operations
Could use bitwise operations—so why not? String processing is a common case
MIPS byte/halfword load/store operations
--lb rt, offset(rs) lh rt, offset(rs) Sign extend to 32 bits in rt
--lbu rt, offset(rs) lhu rt, offset(rs) Zero extend to 32 bits in rt
--sb rt, offset(rs) sh rt, offset(rs) Store just rightmost byte/halfword
String Copy Example
C code (naive): Null-terminated ASCII string
void strcpy (char x[], char y[]){ int i; i = 0; while ((x[i]=y[i])!='\0') # copy xy until null i += 1;}
Addresses of x, y in $a0, $a1 i in $s0
String Copy Example
MIPS code:
strcpy: addi $sp, $sp, -4 # push $s0 onto stack sw $s0, 0($sp) # add $s0, $zero, $zero # i = 0L1: add $t1, $s0, $a1 # addr of y[i] in $t1 lbu $t2, 0($t1) # $t2 = y[i] add $t3, $s0, $a0 # addr of x[i] in $t3 sb $t2, 0($t3) # x[i] = y[i] beq $t2, $zero, L2 # exit loop if y[i] == 0 addi $s0, $s0, 1 # i = i + 1 j L1 # next iteration of loopL2: lw $s0, 0($sp) # pop $s0 from stack addi $sp, $sp, 4 # jr $ra # and return
[Bottom testing & pointer addressing saves 2 lines from the loop. Not using s0 saves 4 other lines.]
We'd like to be able to load a 32-bit constant into a register, for this we must use two instructions
a new "load upper immediate" instruction
lui $t0, 1010101010101010
Then must get the lower order bits right, use ori $t0, $t0, 1010101010101010
32-bit Constants
16 0 8 10101010101010102
1010101010101010
0000000000000000 1010101010101010
0000000000000000
1010101010101010 1010101010101010
§2.10 M
IPS
Addressing for 32-B
it Imm
ediates and A
ddresses
Branch Addressing
Branch instructions specify Opcode, two registers, target address beq $t0, $s3, LoopEnd
Most branch targets are near branch Forward or backward (max is ±215)
op rs rt constant or address
6 bits 5 bits 5 bits 16 bits
PC-relative addressing Target address = PC + offset × 4 PC already incremented by 4 by this time
MIPS also has an unconditional branch instruction or jump instruction:
j label #go to label
Other Control Flow Instructions
Instruction Format (J Format):0x02 26-bit address
PC4
32
26
32
00
from the low order 26 bits of the jump instruction
Jump Addressing
Jump (j and jal) targets could be anywhere in text segment
Encode full address in instruction
op address
6 bits 26 bits
Pseudo-Direct jump addressing Target address = PC31…28 : (address × 4)
Target Addressing Example
Loop code from earlier example Assume Loop at location 80000
Loop: sll $t1, $s3, 2 80000 0 0 19 9 2 0
add $t1, $t1, $s6 80004 0 9 22 9 0 32
lw $t0, 0($t1) 80008 35 9 8 0
bne $t0, $s5, Exit 80012 5 8 21 2
addi $s3, $s3, 1 80016 8 19 19 1
j Loop 80020 2 20000
Exit: … 80024
Branching Far Away
What if the branch destination is further away than can be captured in 16 bits?
The assembler comes to the rescue – it inserts an unconditional jump to the branch target and inverts the condition
beq $s0, $s1, L1_far
becomes
bne $s0, $s1, L2j L1_far
L2:
Addressing Mode Summary