Sei sulla pagina 1di 31

CSCI-365

Computer Organization
Lecture 5

Note: Some slides and/or pictures in the following are adapted from:
Computer Organization and Design, Patterson & Hennessy, ©2005
Some slides and/or pictures in the following are adapted from:
slides ©2008 UCB
Function Call Bookkeeping

• Registers play a major role in keeping track of


information for function calls
• Register conventions:
– Return address $ra
– Arguments $a0, $a1, $a2, $a3
– Return value $v0, $v1
– Local variables $s0, $s1, … , $s7
• The stack is also used; more later
Function Call Bookkeeping

... sum(a,b);... /* a,b:$s0,$s1 */


}
int sum(int x, int y) {
return x+y;
}
address
1000 add $a0,$s0,$zero # x = a
1004 add $a1,$s1,$zero # y = b
1008 addi $ra,$zero,1016 # $ra=1016
1012 j sum # jump to sum
1016 ...
2000 sum: add $v0,$a0,$a1
2004 jr $ra # new instruction
Function Call Bookkeeping
... sum(a,b);... /* a,b:$s0,$s1 */
}
int sum(int x, int y) {
return x+y;
}
• Question: Why use jr here? Why not simply use j?
– Answer: sum might be called by many places, so we can’t return
to a fixed place. The calling proc to sum must be able to say
“return here” somehow
2000 sum: add $v0,$a0,$a1
2004 jr $ra # new instruction
Function Call Bookkeeping

• Single instruction to jump and save return address: jump


and link (jal)
• Before:
1008 addi $ra,$zero,1016 #$ra=1016
1012 j sum #goto sum
• After:
1008 jal sum # $ra=1012,goto sum
• Why have a jal? Make the common case fast: function
calls are very common. Also, you don’t have to know
where the code is loaded into memory with jal
Function Call Bookkeeping

• Syntax for jal (jump and link) is same as for j


(jump):
jal label
• jal should really be called laj for “link and
jump”:
– Step 1 (link): Save address of next instruction into
$ra (Why next instruction? Why not current one?)
– Step 2 (jump): Jump to the given label
Function Call Bookkeeping

• Syntax for jr (jump register):


jr register
• Instead of providing a label to jump to, the jr
instruction provides a register which contains an
address to jump to
• Very useful for function calls:
– jal stores return address in register ($ra)
– jr $ra jumps back to that address
Nested Procedures

int sumSquare(int x, int y) {


return mult(x,x)+ y;
}
• Something called sumSquare, now sumSquare is
calling mult
• So there’s a value in $ra that sumSquare wants to jump
back to, but this will be overwritten by the call to mult
• Need to save sumSquare return address before call to
mult
Nested Procedures

• In general, may need to save some other info in


addition to $ra
• When a program is run, there are 3 important memory
areas allocated:
– Static: Variables declared once per program, cease to exist
only after execution completes. E.g., C globals
– Heap: Variables declared dynamically
– Stack: Space to be used by procedure during execution; this
is where we can save register values
Memory Allocation
Address Space for saved
 Stack
$sp procedure information
stack
pointer

Explicitly created space,


Heap
e.g., malloc(); C pointers

Static Variables declared


once per program
Code Program
0
Using the Stack for Data Storage
Analogy:
Cafeteria
sp stack of
b
plates/trays
a
Push c Pop x

sp c
b b
a sp a x = mem[sp]
sp = sp – 4
sp = sp + 4
mem[sp] = c

Effects of push and pop operations on a stack.

push: addi $sp,$sp,-4 pop: lw $t5,0($sp)


sw $t4,0($sp) addi $sp,$sp,4
The Stack
The register scratchpad for a procedure seems volatile –
it seems to disappear every time we switch procedures –
a procedure’s values are therefore backed up in memory
on a stack
High address
Proc A’s values Proc A

call Proc B
Proc B’s values …
call Proc C
Proc C’s values …
… return
Stack grows return
this way return
Low address
Using the Stack

• So we have a register $sp which always points


to the last used space in the stack
• To use stack, we decrement this pointer by the
amount of space we need and then fill it with info
• So, how do we compile this?
int sumSquare(int x, int y) {
return mult(x,x)+ y;
}
Using the Stack
int sumSquare(int x, int y) {
sumSquare: return mult(x,x)+ y; }
“push” addi $sp,$sp,-8 # space on stack
sw $ra, 4($sp) # save ret addr
sw $a1, 0($sp) # save y
add $a1,$a0,$zero # mult(x,x)
jal mult # call mult
lw $a1, 0($sp) # restore y
add $v0,$v0,$a1 # mult()+y
“pop” lw $ra, 4($sp) # get ret addr
addi $sp,$sp,8 # restore stack
jr $ra
mult: ...
Steps for Making a Procedure Call

• Save necessary values onto stack


• Assign argument(s), if any
• jal call
• Restore values from stack
Illustrating a Procedure Call
main
Prepare
to call
PC jal proc
Prepare
to continue proc
Save, etc.

Restore
jr $ra

Figure 6.1 Relationship between the main program and a procedure.


Nested Procedure Calls
main
Prepare
to call
PC jal abc Procedure
Prepare abc
to continue abc Procedure
Save xyz
xyz

jal xyz

Restore
Text version jr $ra jr $ra
is incorrect

Example of nested procedure calls.


$0 0 $zero A 4-b yte word
$1 $at Reserved for assembler use 3
sits in consecutive
$2 $v0
Procedure results
memory addresses 2
1
Recalling
$3 $v1 according to the
$4
$5
$a0
$a1 Procedure
big-endian order
(most significant
0
Register
Saved byte has the
$6
$7
$a2
$a3
arguments
lowest address) Conventions
$8 $t0
$9 $t1 Byte numbering: 3 2 1 0
$10 $t2 When loading
$11 $t3 Temporary a byte into a
$12 $t4 values register, it goes
$13 $t5 in the low end Byte
$14 $t6
$15 $t7 Word
$16 $s0 Doublew ord
$17 $s1
$18 $s2 Saved
$19 $s3 across
Operands procedure
$20 $s4
$21 $s5 calls
$22 $s6
$23 $s7 A doubleword
$24 $t8 More sits in consecutive
$25 $t9 temporaries registers or
$26 $k0 memory locations
Registers and
$27 $k1 Reserved for OS (kernel) according to the data sizes in
$28 $gp Global pointer big-endian order
$29 $sp Stack pointer (most significant MIPS.
Saved word comes first)
$30 $fp Frame pointer
$31 $ra Return address
Hex address 00000000
Memory Reserved 1 M words
00400000
Map in Text segment
Program
MIPS 63 M words

10000000
Addressable Static data
with 16-bit 10008000
signed offset Data segment
1000ffff
Dynamic data

$gp 448 M words


$28 $sp
$29
$30
$fp
Stack Stack segment

7ffffffc
80000000
Second half of address
space reserved for
memory-mapped I/O
Overview of the memory address space in MIPS.
Basic Structure of a Function
Prologue
entry_label: ra
addi $sp,$sp,-framesize
sw $ra, framesize-4($sp) # save $ra
save other regs if need be
...
memory
Body (call other functions…)
Epilogue
restore other regs if need be
lw $ra, framesize-4($sp) # restore $ra
addi $sp,$sp,framesize
jr $ra
Example

int leaf_example (int g, int h, int i, int j)


{
int f ;
f = (g + h) – (i + j);
return f;
}
Example
Example

int fib (int n)


{
if (n == 0) return 1;
if (n == 1) return 1;
return ( fib(n-1) + fib(n-2) );
}
Example

int fact (int n)


{
if (n < 1) return 1;
else return (n * fact(n-1));
}
Rules for Procedures

• Called with a jal instruction, returns with a jr


$ra
• Accepts up to 4 arguments in $a0, $a1, $a2
and $a3
• Return value is always in $v0 (and if necessary
in $v1)
• Must follow register conventions. So what are
they?
Register Conventions

• CalleR: the calling function


• CalleE: the function being called
• When callee returns from executing, the caller needs to
know which registers are guaranteed to be unchanged
(saved registers) and which registers may have changed
(volatile registers)
• Register Conventions: A set of generally accepted rules
as to which registers will be unchanged after a
procedure call (jal) and which may be changed
Register Conventions - saved

• $0: No Change. Always 0


• $s0-$s7: Restore if you change. Very important, that’s
why they’re called saved registers. If the callee changes
these in any way, it must restore the original values
before returning
• $sp: Restore if you change. The stack pointer must point
to the same place before and after the jal call, or else
the caller won’t be able to restore values from the stack
• HINT – All saved registers start with S!
Register Conventions - volatile

• $ra: Can Change. The jal call itself will change this
register. Caller needs to save on stack if nested call
• $v0-$v1: Can Change. These will contain the new
returned values
• $a0-$a3: Can Change. These are volatile argument
registers. Caller needs to save if they’ll need them after
the call
• $t0-$t9: Can Change. That’s why they’re called
temporary: any procedure may change them at any time.
Caller needs to save if they’ll need them afterwards
Register Conventions

• What do these conventions mean?


– If function R calls function E, then function R must
save any temporary registers that it may be using
onto the stack before making a jal call
– Function E must save any S (saved) registers it
intends to use before garbling up their values
– Remember: Caller/callee need to save only
temporary/saved registers they are using, not all
registers
6.3 Parameters and Results
Stack allows us to pass/return an arbitrary number of values

$sp z
Local y Frame for
..
variables . current
Saved procedure
registers
Old ($fp)
$sp c $fp c
b Frame for b Frame for
a current a previous
.. procedure .. procedure
. .
$fp

Before calling After calling


Figure 6.5 Use of the stack by a procedure.

Computer Architecture, Instruction-Set Architecture Slide 30


Example of Using the Stack

Saving $fp, $ra, and $s0 onto the stack and restoring
them at the end of the procedure

proc: sw $fp,-4($sp) # save the old frame pointer


addi $fp,$sp,0 # save ($sp) into $fp
addi $sp,$sp,–12 # create 3 spaces on top of stack
sw $ra,-8($fp) # save ($ra) in 2nd stack element
sw $s0,-12($fp) # save ($s0) in top stack element
$sp .
($s0)
($ra) .
($fp) .
$sp lw $s0,-12($fp) # put top stack element in $s0
$fp lw $ra,-8($fp) # put 2nd stack element in $ra
addi $sp,$fp, 0 # restore $sp to original state
$fp lw $fp,-4($sp) # restore $fp to original state
jr $ra # return from procedure

Computer Architecture, Instruction-Set Architecture Slide 31

Potrebbero piacerti anche