prof. hakim weatherspoon cs 3410, spring · pdf fileprof. hakim weatherspoon. cs 3410, spring...
TRANSCRIPT
Prof. Hakim WeatherspoonCS 3410, Spring 2015
Computer ScienceCornell University
See P&H 2.8 and 2.12, and A.5-6
Upcoming agenda• PA1 due yesterday
• PA2 available and discussed during lab section this week• PA2 Work-in-Progress due Monday, March 16th
• PA2 due Thursday, March 26th
• HW2 available next week, due before Prelim2 in April
• Spring break: Saturday, March 28th to Sunday, April 5th
Review: Calling Conventions • call a routine (i.e. transfer control to procedure)• pass arguments
• fixed length, variable length, recursively
• return to the caller• Putting results in a place where caller can find them
• Manage register
Today • More on Calling Conventions• globals vs local accessible data• callee vs caller saved registers• Calling Convention examples and debugging
Review: Calling Conventions• call a routine (i.e. transfer control to procedure)• pass arguments
• fixed length, variable length, recursively
• return to the caller• Putting results in a place where caller can find them
• Manage register
Today • More on Calling Conventions• globals vs local accessible data• callee vs caller saved registers• Calling Convention examples and debuggingWarning: There is no one true MIPS calling convention.
lecture != book != gcc != spim != web
Return address: $31 (ra)Stack pointer: $29 (sp)Frame pointer: $30 (fp)First four arguments: $4-$7 (a0-a3)Return result: $2-$3 (v0-v1)Callee-save free regs: $16-$23 (s0-s7)Caller-save free regs: $8-$15,$24,$25 (t0-t9)Reserved: $26, $27 (k0-k1)Global pointer: $28 (gp)Assembler temporary: $1 (at)
r0 $zero zeror1 $at assembler tempr2 $v0 function
return valuesr3 $v1r4 $a0
functionarguments
r5 $a1r6 $a2r7 $a3r8 $t0
temps(caller save)
r9 $t1r10 $t2r11 $t3r12 $t4r13 $t5r14 $t6r15 $t7
r16 $s0
saved(callee save)
r17 $s1r18 $s2r19 $s3r20 $s4r21 $s5r22 $s6r23 $s7r24 $t8 more temps
(caller save)r25 $t9r26 $k0 reserved for
kernelr27 $k1r28 $gp global data pointerr29 $sp stack pointerr30 $fp frame pointerr31 $ra return address
• first four arg words passed in $a0, $a1, $a2, $a3• remaining arg words passed in parent’s stack frame• return value (if any) in $v0, $v1• stack frame at $sp
– contains $ra (clobbered on JAL to sub-functions)– contains $fp– contains local vars (possibly clobbered by sub-functions)– contains extra arguments to sub-functions(i.e. argument “spilling”)– contains space for first 4 arguments to sub-functions
• callee save regs are preserved• caller save regs are not preserved• Global data accessed via $gp
saved rasaved fp
saved regs($s0 ... $s7)
locals
outgoingargs
$fp
$sp
Bottom of current stack frame
Top of the stack
Global variables in data segment• Exist for all time, accessible to all routines
Dynamic variables in heap segment• Exist between malloc() and free()
Local variables in stack frame• Exist solely for the duration of the stack frame
Dangling pointers into freed heap mem are badDangling pointers into old stack frames are bad
• C lets you create these, Java does not• E.g. int *foo() { int a; return &a; }
0xfffffffc
0x00000000
top
bottom
0x7ffffffc0x80000000
0x10000000
0x00400000
system reserved
stack
system reserved
code (text)
static data
dynamic data (heap)
.data
.textPC
Return address: $31 (ra)Stack pointer: $29 (sp)Frame pointer: $30 (fp)First four arguments: $4-$7 (a0-a3)Return result: $2-$3 (v0-v1)Callee-save free regs: $16-$23 (s0-s7)Caller-save free regs: $8-$15,$24,$25 (t0-t9)Reserved: $26, $27Global pointer: $28 (gp)Assembler temporary: $1 (at)
Callee-save register:• Assumes register not changed across procedure call • Thus, callee must save the previous contents of the register on
procedure entry, restore just before procedure return• E.g. $ra, $fp, $s0-s7
Caller-save register:• Assumes that a caller can clobber contents of register• Thus, caller must save the previous contents of the register
before proc call• Caller, then, restores after the call to subroutine returns• E.g. $a0-a3, $v0-$v1, $t0-$t9
MIPS calling convention supports both
Callee-save register:• Assumes register not changed across procedure call • Thus, callee must save the previous contents of the register on
procedure entry, restore just before procedure return• E.g. $ra, $fp, $s0-s7, $gp• Also, $sp
Caller-save register:• Assumes that a caller can clobber contents of register• Thus, caller must save the previous contents of the register
before proc call• Caller, then, restores after the call to subroutine returns• E.g. $a0-a3, $v0-$v1, $t0-$t9
MIPS calling convention supports both
Caller-save: If necessary… ($t0 .. $t9)• save before calling anything; restore after it returns
Callee-save: Always… ($s0 .. $s7)• save before modifying; restore before returning
Caller-save registers are responsibility of the caller• Caller-save register values saved only if used after call/return• The callee function can use caller-saved registers
Callee-save register are the responsibility of the callee• Values must be saved by callee before they can be used • Caller can assume that these registers will be restored
Save if want to use after a call
Save before use
Caller-save: If necessary… ($t0 .. $t9)• save before calling anything; restore after it returns
Callee-save: Always… ($s0 .. $s7)• save before modifying; restore before returning
MIPS ($t0-$t9), x86 (eax, ecx, and edx) are caller-save…• … a function can freely modify these registers• … but must assume that their contents have been destroyed if it in
turns calls a function. MIPS ($s0 - $s7), x86 (ebx, esi, edi, ebp, esp) are callee-save
• A function may call another function and know that the callee-save registers have not been modified
• However, if it modifies these registers itself, it must restore them to their original values before returning.
Caller-save: If necessary… ($t0 .. $t9)• save before calling anything; restore after it returns
Callee-save: Always… ($s0 .. $s7)• save before modifying; restore before returning
A caller-save register must be saved and restored around any call to a subroutine. In contrast, for a callee-save register, a caller does not need to do any extra work at a call site (b/c the calleesaves and restores the register if it is used).
Caller-save: If necessary… ($t0 .. $t9)• save before calling anything; restore after it returns
Callee-save: Always… ($s0 .. $s7)• save before modifying; restore before returning
CALLER SAVED: MIPS calls these temporary registers, $t0-t9• the calling routine saves the registers that it does not want a
called procedure to overwrite • register values are NOT preserved across procedure calls
CALLEE SAVED: MIPS calls these saved registers, $s0-s8 • register values are preserved across procedure calls • the called procedure saves register values in its Activation
Record (AR), uses the registers for local variables, restores register values before it returns.
Caller-save: If necessary… ($t0 .. $t9)• save before calling anything; restore after it returns
Callee-save: Always… ($s0 .. $s7)• save before modifying; restore before returning
Registers $t0-$t9 are caller-saved registers• … that are used to hold temporary quantities• … that need not be preserved across calls
Registers $s0-s8 are callee-saved registers• … that hold long-lived values• … that should be preserved across calls
Assume caller is using the registers Callee must save on entry, restore on exit
Pays off if caller is actually using the registers, else the save and restore are wasted
main:addiu $sp,$sp,-32sw $31,28($sp)sw $30, 24($sp)sw $17, 20($sp)sw $16, 16($sp)addiu $30, $sp, 28
…[use $16 and $17]
…lw $31,28($sp)lw $30,24($sp)lw $17, 20$sp)lw $16, 16($sp)addiu $sp,$sp,32jr $31
Assume caller is using the registersCallee must save on entry, restore on exit
Pays off if caller is actually using the registers, else the save and restore are wasted
main:addiu $sp,$sp,-32sw $ra,28($sp)sw $fp, 24($sp)sw $s1, 20($sp)sw $s0, 16($sp)addiu $fp, $sp, 28
…[use $s0 and $s1]
…lw $ra,28($sp)lw $fp,24($sp)lw $s1, 20$sp)lw $s0, 16($sp)addiu $sp,$sp,32jr $ra
Assume the registers are free for the taking, clobber them
But since other subroutines will do the same, must protect values that will be used laterBy saving and restoring them before and after subroutine invocations
Pays off if a routine makes few calls to other routines with values that need to be preserved
main:…[use $8 & $9]…addiu $sp,$sp,-8sw $9, 4($sp)sw $8, 0($sp)jal multlw $9, 4($sp)lw $8, 0($sp)addiu $sp,$sp,8…[use $8 & $9]
Assume the registers are free for the taking, clobber themBut since other subroutines will do the same, must protect values that will be used laterBy saving and restoring them before and after subroutine invocations
Pays off if a routine makes few calls to other routines with values that need to be preserved
main:…[use $t0 & $t1]…addiu $sp,$sp,-8sw $t1, 4($sp)sw $t0, 0($sp)jal multlw $t1, 4($sp)lw $t0, 0($sp)addiu $sp,$sp,8…[use $t0 & $t1]
Return address: $31 (ra)Stack pointer: $29 (sp)Frame pointer: $30 (fp)First four arguments: $4-$7 (a0-a3)Return result: $2-$3 (v0-v1)Callee-save free regs: $16-$23 (s0-s7)Caller-save free regs: $8-$15,$24,$25 (t0-t9)Reserved: $26, $27Global pointer: $28 (gp)Assembler temporary: $1 (at)
• first four arg words passed in $a0, $a1, $a2, $a3• remaining arg words passed in parent’s stack frame• return value (if any) in $v0, $v1• stack frame at $sp
– contains $ra (clobbered on JAL to sub-functions)– contains $fp– contains local vars (possibly clobbered by sub-functions)– contains extra arguments to sub-functions(i.e. argument “spilling)– contains space for first 4 arguments to sub-functions
• callee save regs are preserved• caller save regs are not• Global data accessed via $gp
saved rasaved fp
saved regs($s0 ... $s7)
locals
outgoingargs
$fp
$sp
Bottom of current stack frame
Top of the stack
saved rasaved fp
saved regs($s0 ... $s7)
locals
outgoingargs
fp
sp
Assume a function uses two callee-save registers. How do we allocate a stack frame? How large is the stack frame? What should be stored in the stack frame? Where should everything be stored?
saved rasaved fp
saved regs($s0 ... $s7)
locals
outgoingargs
fp
sp
ADDIU $sp, $sp, -32 # allocate frameSW $ra, 28($sp) # save $raSW $fp, 24($sp) # save old $fpSW $s1, 20($sp) # save ...SW $s0, 16($sp) # save ...ADDIU $fp, $sp, 28 # set new frame ptr… ...BODY… ...LW $s0, 16($sp) # restore …LW $s1, 20($sp) # restore …LW $fp, 24($sp) # restore old $fpLW $ra, 28($sp) # restore $raADDIU $sp,$sp, 32 # dealloc frameJR $ra
sp
blue() {pink(0,1,2,3,4,5);
}saved fp
saved rafp
arguments
saved regsblue
sp
arguments
saved ra
saved regs
local variables
arguments
saved regs
blue() {pink(0,1,2,3,4,5);
}pink(int a, int b, int c, int d, int e, int f) {
orange(10,11,12,13,14);}
saved fp
saved ra
saved fp
fp
blue
pink
sp
arguments
saved ra
saved regs
local variables
arguments
saved regs
saved ra
blue() {pink(0,1,2,3,4,5);
}pink(int a, int b, int c, int d, int e, int f) {
orange(10,11,12,13,14);}orange(int a, int b, int c, int, d, int e) {
char buf[100];gets(buf); // read string, no check!
}
local variables
saved fp
saved ra
saved fp
saved fp
fp
blue
pink
orange
buf[100]
sp
arguments
saved ra
saved regs
local variables
arguments
saved regs
saved ra
blue() {pink(0,1,2,3,4,5);
}pink(int a, int b, int c, int d, int e, int f) {
orange(10,11,12,13,14);}orange(int a, int b, int c, int, d, int e) {
char buf[100];gets(buf); // read string, no check!
}
local variables
saved fp
saved ra
saved fp
saved fp
fp
What happens if more than 100 bytes is written to buf?
buf[100]
int test(int a, int b) {int tmp = (a&b)+(a|b);int s = sum(tmp,1,2,3,4,5);int u = sum(s,tmp,b,a,b,a);return u + a + b;
}
int test(int a, int b) {int tmp = (a&b)+(a|b);int s = sum(tmp,1,2,3,4,5);int u = sum(s,tmp,b,a,b,a);return u + a + b;
}
test:
MOVE $s0, $a0MOVE $s1, $a1AND $t0, $a0, $a1OR $t1, $a0, $a1ADD $t0, $t0, $t1MOVE $a0, $t0LI $a1, 1LI $a2, 2LI $a3, 3LI $t1, 4SW $t1 16($sp)LI $t1, 5SW $t1, 20($sp)SW $t0, 24($sp)JAL sumNOP
LW $t0, 24($sp)MOVE $a0, $v0 # sMOVE $a1, $t0 # tmpMOVE $a2, $s1 # bMOVE $a3, $s0 # aSW $s1, 16($sp)SW $s0, 20($sp)JAL sumNOP
# add u (v0) and a (s0)ADD $v0, $v0, $s0ADD $v0, $v0, $s1# $v0 = u + a + b
Prologue
Epilogue
int test(int a, int b) {int tmp = (a&b)+(a|b);int s = sum(tmp,1,2,3,4,5);int u = sum(s,tmp,b,a,b,a);return u + a + b;
}
test:
MOVE $s0, $a0MOVE $s1, $a1AND $t0, $a0, $a1OR $t1, $a0, $a1ADD $t0, $t0, $t1MOVE $a0, $t0LI $a1, 1LI $a2, 2LI $a3, 3LI $t1, 4SW $t1 16($sp)LI $t1, 5SW $t1, 20($sp)SW $t0, 24($sp)JAL sumNOP
LW $t0, 24($sp)MOVE $a0, $v0 # sMOVE $a1, $t0 # tmpMOVE $a2, $s1 # bMOVE $a3, $s0 # aSW $s1, 16($sp)SW $s0, 20($sp)JAL sumNOP
# add u (v0) and a (s0)ADD $v0, $v0, $s0ADD $v0, $v0, $s1# $v0 = u + a + b
Prologue
Epilogue
How many bytes do we need to allocate for the stack frame?a) 24b) 32c) 40d) 44e) 48
int test(int a, int b) {int tmp = (a&b)+(a|b);int s = sum(tmp,1,2,3,4,5);int u = sum(s,tmp,b,a,b,a);return u + a + b;
}
test:
MOVE $s0, $a0MOVE $s1, $a1AND $t0, $a0, $a1OR $t1, $a0, $a1ADD $t0, $t0, $t1MOVE $a0, $t0LI $a1, 1LI $a2, 2LI $a3, 3LI $t1, 4SW $t1 16($sp)LI $t1, 5SW $t1, 20($sp)SW $t0, 24($sp)JAL sumNOP
LW $t0, 24($sp)MOVE $a0, $v0 # sMOVE $a1, $t0 # tmpMOVE $a2, $s1 # bMOVE $a3, $s0 # aSW $s1, 16($sp)SW $s0, 20($sp)JAL sumNOP
# add u (v0) and a (s0)ADD $v0, $v0, $s0ADD $v0, $v0, $s1# $v0 = u + a + b
saved rasaved fp
saved regs($s0 and $s1)
locals($t0)
outgoing argsspace for a0 - a3
and 5th and 6th arg
$fp
$sp
Prologue
Epilogue
int test(int a, int b) {int tmp = (a&b)+(a|b);int s = sum(tmp,1,2,3,4,5);int u = sum(s,tmp,b,a,b,a);return u + a + b;
}
test:
MOVE $s0, $a0MOVE $s1, $a1AND $t0, $a0, $a1OR $t1, $a0, $a1ADD $t0, $t0, $t1MOVE $a0, $t0LI $a1, 1LI $a2, 2LI $a3, 3LI $t1, 4SW $t1 16($sp)LI $t1, 5SW $t1, 20($sp)SW $t0, 24($sp)JAL sumNOP
LW $t0, 24($sp)MOVE $a0, $v0 # sMOVE $a1, $t0 # tmpMOVE $a2, $s1 # bMOVE $a3, $s0 # aSW $s1, 16($sp)SW $s0, 20($sp)JAL sumNOP
# add u (v0) and a (s0)ADD $v0, $v0, $s0ADD $v0, $v0, $s1# $v0 = u + a + b
saved rasaved fp
$fp
$sp
Prologue
Epilogue
saved reg $s1saved reg $s0
local $t0outgoing 6th argoutgoing 5th arg
space for $a3space for $a2space for $a1space for $a0
48
1216
0
202428323640
# allocate frame# save $ra# save old $fp# callee save ...# callee save ...# set new frame ptr
...
...
# restore …# restore …# restore old $fp# restore $ra# dealloc frame
test:
saved rasaved fp
$fp
$sp
saved reg $s1saved reg $s0
local $t0outgoing 6th argoutgoing 5th arg
space for $a3space for $a2space for $a1space for $a0
48
1216
0
202428323640
# allocate frame# save $ra# save old $fp# callee save ...# callee save ...# set new frame ptr
...
...
# restore …# restore …# restore old $fp# restore $ra# dealloc frame
test: ADDIU $sp, $sp, -44SW $ra, 40($sp)SW $fp, 36($sp)SW $s1, 32($sp)SW $s0, 28($sp)ADDIU $fp, $sp, 40
LW $s0, 28($sp)LW $s1, 32($sp)LW $fp, 36($sp)LW $ra, 40($sp)ADDIU $sp, $sp, 44JR $raNOP
Body(previous slide, Activity #1)
saved rasaved fp
$fp
$sp
saved reg $s1saved reg $s0
local $t0outgoing 6th argoutgoing 5th arg
space for $a3space for $a2space for $a1space for $a0
48
1216
0
202428323640
Space for $t0 and six argsto pass to subroutine
Can we optimize the assembly code at all?
int test(int a, int b) {int tmp = (a&b)+(a|b);int s =
sum(tmp,1,2,3,4,5);int u =
sum(s,tmp,b,a,b,a);return u + a + b;
}
test:
MOVE $s0, $a0MOVE $s1, $a1AND $t0, $a0, $a1OR $t1, $a0, $a1ADD $t0, $t0, $t1MOVE $a0, $t0LI $a1, 1LI $a2, 2LI $a3, 3LI $t1, 4SW $t1 16($sp)LI $t1, 5SW $t1, 20($sp)SW $t0, 24($sp)JAL sumNOP
LW $t0, 24($sp)MOVE $a0, $v0 # sMOVE $a1, $t0 # tmpMOVE $a2, $s1 # bMOVE $a3, $s0 # aSW $s1, 16($sp)SW $s0, 20($sp)JAL sumNOP
# add u (v0) and a (s0)ADD $v0, $v0, $s0ADD $v0, $v0, $s1# $v0 = u + a + b
Prologue
Epilogue
How can we optimize the assembly code?
# allocate frame# save $ra# save old $fp# callee save ...# callee save ...# set new frame ptr
...
...# restore …# restore …# restore old $fp# restore $ra# dealloc frame
test: ADDIU $sp, $sp, -44SW $ra, 40($sp)SW $fp, 36($sp)SW $s1, 32($sp)SW $s0, 28($sp)ADDIU $fp, $sp, 40
LW $s0, 28($sp)LW $s1, 32($sp)LW $fp, 36($sp)LW $ra, 40($sp)ADDIU $sp, $sp, 44JR $raNOP
Body
24 bytes = 6x 4 bytes ($ra + $fp + 4 args)
saved rasaved fp
saved regs($s0 ... $s7)
locals
outgoingargs
$fp
$sp
Leaf function does not invoke any other functionsint f(int x, int y) { return (x+y); }
Optimizations?No saved regs (or locals)No outgoing argsDon’t push $raNo frame at all?
Maybe.
saved rasaved fp
saved regs($s0 ... $s7)
locals
outgoingargs
$fp
$sp
Given a running program (a process), how do we know what is going on (what function is executing, what arguments were passed to where, where is the stack and current stack frame, where is the code and data, etc)?
0xfffffffc
0x00000000
top
bottom
0x7ffffffc0x80000000
0x10000000
0x00400000
system reserved
stack
system reserved
code (text)
static data
dynamic data (heap)
.data
.textPC
init(): 0x400000printf(s, …): 0x4002B4vnorm(a,b): 0x40107Cmain(a,b): 0x4010A0pi: 0x10000000str1: 0x10000004
0x000000000x004010c4
0x00000000
0x00000000
0x7FFFFFF40x000000000x00000000
0x0040010c
0x000000150x100000040x00401090
0x00000000
0x00000000
CPU:$pc=0x004003C0$sp=0x7FFFFFAC$ra=0x00401090
0x7FFFFFB0
What func is running?Who called it?Has it called anything?Will it?Args?Stack depth?Call trace?
0x7FFFFFDC
init(): 0x400000printf(s, …): 0x4002B4vnorm(a,b): 0x40107Cmain(a,b): 0x4010A0pi: 0x10000000str1: 0x10000004
0x000000000x004010c4
0x00000000
0x00000000
0x7FFFFFF40x000000000x00000000
0x0040010c
0x000000150x100000040x00401090
0x00000000
0x00000000
CPU:$pc=0x004003C0$sp=0x7FFFFFAC$ra=0x00401090
0x7FFFFFB0
What func is running?Who called it?Has it called anything?Will it?Args?Stack depth?Call trace?
0x7FFFFFDC
printfvnorm
nono
printf, vnorm, main, init
Str1 and 0x154
0x7FFFFFAC
0x7FFFFFB40x7FFFFFB80x7FFFFFBC0x7FFFFFC00x7FFFFFC40x7FFFFFC80x7FFFFFCA0x7FFFFFD00x7FFFFFD40x7 …D8
DCE0
Memory
rafpa3a2a1a0
rafpa3a2a1a0
a0
ra
E4E8EA
…F0…F4
a1a2a3fpra
b/c no space for outgoing args
0x7FFFFFA8
main
vnorm
0x7FFFFFC4printf
• How to write and Debug a MIPS program using calling convention
• first four arg words passed in $a0, $a1, $a2, $a3• remaining arg words passed in parent’s stack frame• return value (if any) in $v0, $v1• stack frame at $sp
– contains $ra (clobbered on JAL to sub-functions)– contains $fp– contains local vars (possibly clobbered by sub-functions)– contains extra arguments to sub-functions(i.e. argument “spilling)– contains space for first 4 arguments to sub-functions
• callee save regs are preserved• caller save regs are not• Global data accessed via $gp
saved rasaved fp
saved regs($s0 ... $s7)
locals
outgoingargs
$fp
$sp