EE 109 Unit 16 Stack Frames 2 Arguments and Return Values Number - - PowerPoint PPT Presentation

ee 109 unit 16 stack frames
SMART_READER_LITE
LIVE PREVIEW

EE 109 Unit 16 Stack Frames 2 Arguments and Return Values Number - - PowerPoint PPT Presentation

1 EE 109 Unit 16 Stack Frames 2 Arguments and Return Values Number Name Purpose MIPS convention is to $0 $zero Constant 0 $1 $at Assembler temporary use certain registers for (psuedo-instrucs.) this task $2-$3 $v0-$v1 Return


slide-1
SLIDE 1

1

EE 109 Unit 16 – Stack Frames

slide-2
SLIDE 2

2

Arguments and Return Values

  • MIPS convention is to

use certain registers for this task

– $a0 - $a3 used to pass up to 4 arguments. If more arguments, use the stack – $v0 used for return value

  • Only 1 return value but it

may be a double-word (64-bits) in which case $v1 will also be used

Number Name Purpose $0 $zero Constant 0 $1 $at Assembler temporary (psuedo-instrucs.) $2-$3 $v0-$v1 Return value ($v1 only used for dword) $4-$7 $a0-$a3 Arguments (first 4 of a subroutine) $8-$15, $24,$25 $t0-$t9 Temporary registers $16-$23 $s0-$s7 Saved registers $26-$27 $k0-$k1 Kernel reserved $28 $gp Global pointer (static global data var’s.) $29 $sp Stack pointer $30 $fp Frame pointer $31 $ra Return address

slide-3
SLIDE 3

3

Arguments and Return Values

void main() { int ans,arg1,arg2; ans = avg(arg1, arg2); } int avg(int a, int b) { int temp=1; // local var’s return a+b >> temp; } ... MAIN: la $s0, arg1 # Get addr. la $s1, arg2 # of arg1/arg2 lw $a0, 0($s0) # Get val. of lw $a1, 0($s1) # arg1/arg2 jal AVG # call function la $s2, ans sw $v0, ($s2) # store ans. ... AVG: li $t0, 1 # temp=1 add $v0,$a0,$a1 # do a+b srav $v0,$v0,$t0 # do shift jr $ra C Code Equivalent Assembly

slide-4
SLIDE 4

4

Assembly & HLL’s

  • When coding in assembly, a programmer can optimize

usage of registers and store only what is needed to memory/stack

– Can pass additional arguments in registers (beyond $a0-$a3) – Can allocate variables to registers (not use memory) – Can handle spilling registers to memory only when necessary

  • When coding in an HLL & using a compiler, certain

conventions are followed that may lead to heavier usage of the stack and memory

– We have to be careful not to overwrite registers that have useful data

slide-5
SLIDE 5

5

Compiler Handling of Subroutines

  • High level languages (HLL) use the stack:

– to save register values including the return address – to pass additional arguments to a subroutine – for storage of local variables declared in the subroutine

  • Compilers usually put data on the stack in a certain
  • rder, which we call a stack "frame"
  • To access this data on the stack a pointer called the

"frame pointer" ($30=$fp) is often used in addition to the normal stack pointer ($sp)

slide-6
SLIDE 6

6

Stack Frame Motivation

  • Assume the following C code
  • Now assume each function was written by a different

programmer on their own (w/o talking to each other)

  • What could go wrong?

int x=5, nums[10]; int main() { caller(x, nums); return 0; } int caller(int z, int* dat) { int a = dat[0]-1; return callee(5)+a+z; } int callee(int val) { return (val+3)/2; }

slide-7
SLIDE 7

7

Stack Frame Motivation

  • The caller needs to ensure the

callee routine does not

  • verwrite a needed register
  • 1. Caller may have his own

arguments in $a0-$a3 and then need to call a subroutine and use $a0-$a3

.text MAIN: la $t0,x lw $a0,0($t0) la $a1,NUMS jal CALLER ... CALLER: lw $s0, 0($a1) addi $s0,$s0,-1 li $a0, 5 jal CALLEE add $v0,$v0,$s0 add $v0,$v0,$a0 jr $ra CALLEE: addi $s0,$a0,3 sra $v0,$s0,1 jr $ra int x=5, nums[10]; int main() { caller(x, nums); return 0; } int caller(int z, int* dat) { int a = dat[0]-1; return callee(5)+a+z; } int callee(int val) { return (val+3)/2; } 1 1

New Value Loaded into $a0 But old value needed here

slide-8
SLIDE 8

8

Stack Frame Motivation

  • The caller needs to ensure the

callee routine does not

  • verwrite a needed register
  • 1. Caller may have his own

arguments in $a0-$a3 and then need to call a subroutine and use $a0-$a3

  • 2. Return address ($ra) [We've

already seen this problem]

.text MAIN: la $t0,x lw $a0,0($t0) la $a1,NUMS jal CALLER ... CALLER: lw $s0, 0($a1) addi $s0,$s0,-1 li $a0, 5 jal CALLEE add $v0,$v0,$s0 add $v0,$v0,$a0 jr $ra CALLEE: addi $s0,$a0,3 sra $v0,$s0,1 jr $ra int x=5, nums[10]; int main() { caller(x, nums); return 0; } int caller(int z, int* dat) { int a = dat[0]-1; return callee(5)+a+z; } int callee(int val) { return (val+3)/2; } 2 2 2

slide-9
SLIDE 9

9

Stack Frame Motivation

  • The caller needs to ensure the

callee routine does not

  • verwrite a needed register
  • 1. Caller may have his own

arguments in $a0-$a3 and then need to call a subroutine and use $a0-$a3

  • 2. Return address ($ra)
  • 3. Register values calculated before

the call but used after the call (e.g. $s0)

.text MAIN: la $t0,x lw $a0,0($t0) la $a1,NUMS jal CALLER ... CALLER: lw $s0, 0($a1) addi $s0,$s0,-1 li $a0, 5 jal CALLEE add $v0,$v0,$s0 add $v0,$v0,$a0 jr $ra CALLEE: addi $s0,$a0,3 sra $v0,$s0,1 jr $ra int x=5, nums[10]; int main() { caller(x, nums); return 0; } int caller(int z, int* dat) { int a = dat[0]-1; return callee(5)+a+z; } int callee(int val) { return (val+3)/2; } 3 3 3

Callee unknowingly

  • verwrites $s0 which

will cause CALLER to malfunction

slide-10
SLIDE 10

10

Solution

  • If you're not sure whether some
  • ther subroutine is using a

register (and needs it later)…

  • Save (push) it to the stack

before you overwrite it

– Recall a push: addi $sp, $sp, -4 sw reg_to_save, 0($sp)

  • Restore (pop) it from the stack

before you return

– Recall a pop: lw reg_to_restore, 0($sp) addi $sp, $sp, 4

.text MAIN: la $t0,x lw $a0,0($t0) la $a1,NUMS jal CALLER ... CALLER: addi $sp,$sp,-4 sw $ra, 0($sp) lw $s0, 0($a1) addi $s0,$s0,-1 addi $sp,$sp,-4 sw $a0,0($sp) li $a0, 5 jal CALLEE lw $a0, 0($sp) addi $sp,$sp,4 add $v0,$v0,$s0 add $v0,$v0,$a0 lw $ra, 0($sp) addi $sp,$sp,4 jr $ra

Save $ra Save $a0 Restore $a0 Restore $ra

slide-11
SLIDE 11

11

Solution

  • If you're not sure whether

some other subroutine is using a register (and needs it later)…

.text MAIN: la $t0,x lw $a0,0($t0) la $a1,NUMS jal CALLER ... CALLER: addi $sp,$sp,-4 sw $ra, 0($sp) lw $s0, 0($a1) addi $s0,$s0,-1 addi $sp,$sp,-4 sw $a0,0($sp) li $a0, 5 jal CALLEE lw $a0, 0($sp) addi $sp,$sp,4 add $v0,$v0,$s0 add $v0,$v0,$a0 lw $ra, 0($sp) addi $sp,$sp,4 jr $ra At start of caller() 0000 0000 7fffeffc $sp 0000 0000 0000 0000 7fffeffc 7fffeff8 7fffeff4 Before 'jal CALLEE' instruction 1000 1230 7fffeff4 0040 208c 0000 0000 7fffeffc 7fffeff8 7fffeff4 Before 'jr $ra' 1000 1230 7fffeffc 0040 208c 0000 0000 7fffeffc 7fffeff8 7fffeff4 $sp $sp 0040208c $ra 10001230 $a0 0040208c $ra 00000005 $a0 0040208c $ra 10001230 $a0 1 2 3 1 2 3

slide-12
SLIDE 12

12

Local Variables

  • A functions local variables are also allocated on the stack

void main() { // Allocate 3 integers int ans, arg1=5, arg2=7; ans = avg(arg1, arg2); } // vars. deallocated here MAIN: addi $sp, $sp, -4 sw $ra, 0($sp) # save $ra # Now allocate 3 integers addi $sp, $sp, -12 li $t0, 5 sw $t0, 4($sp) li $t0, 7 sw $t0, 8($sp) lw $a0, 4($sp) # Get val. of lw $a1, 8($sp) # arg1/arg2 jal AVG # call function sw $v0, 0($sp) # store ans. ... # deallocate local vars addi $sp,$sp,12 lw $ra, 0($sp) addi $sp,$sp,4 jr $ra C Code Equivalent Assembly

arg2=7 7fffeffc $sp Saved $ra 0000 0000 7fffeffc 7fffeff8 7fffeff4 ans arg1=5 7fffeff0 7fffefec 7fffefec $sp

slide-13
SLIDE 13

13

Local Variables

  • Locally declared arrays are also allocated on the stack
  • Be careful: variables and arrays often must start on well-defined

address boundaries

void main() { char mystr[14] = "hello..."; double z; } MAIN: addi $sp, $sp, -4 sw $ra, 0($sp) # save $ra # Now allocate array addi $sp, $sp, -16 # not -14 # May pad to get to 8-byte # boundary.. # now alloc. z addi $sp, $sp, -8 # deallocate local vars addi $sp,$sp,24 lw $ra, 0($sp) addi $sp,$sp,4 jr $ra C Code Equivalent Assembly

7fffeffc $sp Saved $ra 0000 0000 7fffeffc 7fffeff8 7fffeff4 7fffeff0 7fffefec 7fffefe0 $sp z 7fffefe8 7fffefe4 z 7fffefe0 h e l l mystr[3-0] mystr[7-4] mystr[11-8] mystr[13-12]

  • pad
slide-14
SLIDE 14

14

Stack Frames

  • Frame = Def: All data on stack belonging

to a subroutine/function

– Space for arguments (in addition to $a0-$a3) – Space for saved registers ($fp, $s0-$s7, $ra) – Space for local variables (those declared in a function)

void main() { int ans, x, y; ... ans = avg(x, y); } int avg(int a, int b) { int temp=1; // local var’s ... } Subroutines Stack Frame Stack Frame Organization

Saved Regs. Local Vars. (temp)

Main Routine’s Stack Frame

Saved Regs. ($ra,$fp,

  • thers)

Sub-subr’s arguments Subroutine’s arguments (copy of x,y) Local Vars. (ans, x, y) Stack Growth

slide-15
SLIDE 15

15

Accessing Values on the Stack

  • Stack pointer ($sp) is usually used to

access only the top value on the stack

  • To access arguments and local variables,

we need to access values buried in the stack

– We can simply use an offset from $sp [ 8($sp) ]

  • Unfortunately other push operations by

the function may change the $sp requiring different displacements at different times for the same variable

  • This can work, but can be confusing

To access parameters we could try to use some displacement [i.e. d($sp) ] but if $sp changes, must use new d value

$sp + offset

Args. Saved Regs. Local Vars. (temp) Saved Regs. ($ra,$fp,

  • thers)

Args. Local Vars. (ans)

Func1 frame Func2 frame $sp

lw $t0, 16($sp) # access var. x addi $sp,$sp,-4 # $sp changes sw $t0, 20($sp) # access x with # diff. displacement

slide-16
SLIDE 16

16

Frame Pointer

  • Solution: Use another pointer that doesn’t

change during execution of a subroutine

  • We call this the Frame Pointer ($fp) and it

usually points to the base of the current routines frame (i.e. the first word of the stack frame) [other implementations might have it points at the last word of the frame]

  • $fp will not change during the course of

subroutine execution

  • Can use constant offsets from $fp to access

parameters or local variables

– Key 1: $fp doesn’t change during subroutine execution – Key 2: Number of arguments, local variables, and saved registers is known at compile time so compiler can easily know what offsets to use

$sp $fp

  • offset

+ offset

Args. Saved Regs. Local Vars. (temp) Saved Regs. ($ra,$fp,

  • thers)

Args. Local Vars. (ans)

slide-17
SLIDE 17

17

Frame Pointer and Subroutines

  • Problem is that each executing

subroutine needs its own value

  • f $fp
  • The called subroutine must

save the caller’s $fp and setup its own $fp

– Usually performed immediately after allocating frame space and saving $ra

  • The called subroutine must

restore the caller’s $fp before it returns

$fp caller’s FP $sp $fp

  • offset

+ offset

Args. Saved Regs. Local Vars. (temp) Saved Regs. ($ra,$fp,

  • thers)

Args. Local Vars. (ans)

slide-18
SLIDE 18

18

STACK FRAMES

Part II

slide-19
SLIDE 19

19

Review

  • The stack is used to store

– Arguments passed by one subroutine to the next

  • Especially if there are more arguments than can fit in

registers (i.e. MIPS uses $a0-$a3 for arguments…but what if there are 5 arguments)

– Saved register values that a subroutine might need later

  • Best example is $ra

– Local variables

  • The stack will be accessed with $sp but also

with $fp

– Each offset from $fp is a different variable

Local Vars. (temp) Saved Regs. ($ra,$fp,

  • thers)

Args.

slide-20
SLIDE 20

20

Simple Example

  • Prev. $fp

Space for num

  • Prev. $ra

void caller(int a){ callee(1); } int callee(int num){ int x = 6; return x + num; }

.text CALLER: addi $sp,$sp,-12 sw $ra,8($sp) sw $fp,4($sp) addi $fp,$sp,8 sw $a0,4($fp) li $a0, 1 jal CALLEE lw $a0,4($fp) lw $ra,8($sp) lw $fp,4($sp) addi $sp,$sp,12 jr $ra CALLEE: addi $sp,$sp,-12 sw $ra,4($sp) sw $fp,0($sp) addi $fp,$sp,8 li $t0,6 sw $t0,0($fp) add $v0,$t0,$a0 lw $fp,0($sp) lw $ra,4($sp) addi $sp,$sp,12 jr $ra

x Saved $ra Caller’s $fp

Stack during execution of CALLEE C Code Assembly Code

Space for a

Caller Callee Prev. $fp $fp $sp $sp $fp $sp

slide-21
SLIDE 21

21

Example 2

int ans; void main() { int x = 3; ans = avg(1,5); x = x + 1; } int avg(int a, int b) { int temp = 1; return a + b >> temp; }

.text MAIN: ... li $s0, 3 li $a0, 1 li $a1, 5 jal AVG sw $v0,0($gp) addi $s0,$s0,1 sw $s0,-4($fp) ... AVG: addi $sp,$sp,-24 sw $ra,8($sp) sw $fp,4($sp) addi $fp,$sp,20 sw $s0,-20($fp) li $s0,1 sw $s0,-4($fp) add $v0,$a0,$a1 srav $v0,$v0,$s0 lw $s0,-20(fp) lw $fp,4($sp) lw $ra,8($sp) addi $sp,$sp,24 jr $ra

slide-22
SLIDE 22

22

$sp

Example 2

.text MAIN: ... li $s0, 3 li $a0, 1 li $a1, 5 jal AVG sw $v0,0($gp) addi $s0,$s0,1 sw $s0,-4($fp) ... AVG: addi $sp,$sp,-24 sw $ra,8($sp) sw $fp,4($sp) addi $fp,$sp,20 sw $s0,-20($fp) li $s0,1 sw $s0,-4($fp) add $v0,$a0,$a1 srav $v0,$v0,$s0 lw $s0,-20(fp) lw $fp,4($sp) lw $ra,8($sp) addi $sp,$sp,24 jr $ra

Stack during execution of AVG

Saved $ra Saved $fp Saved $s0 Empty temp Empty (arg 0) (arg 1) (arg 2) (arg 3) ...

$sp $sp+4 $sp+8 $sp+12 $sp+16 $sp+20 $sp+24 $sp+28 $sp+32 $sp+36 $fp-20 $fp-16 $fp-12 $fp-8 $fp-4 $fp+4 $fp+8 $fp+12 $fp+16 $fp

x Empty

$fp Convention: Local variable section must start and end on an 8-byte boundary

slide-23
SLIDE 23

23

Old $sp

A Real Example

.file 1 "avg.cpp" .text .align 2 .globl _Z3avgii $LFB2: .ent _Z3avgii _Z3avgii: addiu $sp,$sp,-8 $LCFI0: sw $fp,0($sp) $LCFI1: move $fp,$sp $LCFI2: sw $4,8($fp) sw $5,12($fp) lw $3,8($fp) lw $2,12($fp) addu $3,$3,$2 sra $2,$3,31 srl $2,$2,31 addu $2,$3,$2 sra $2,$2,1 move $sp,$fp lw $fp,0($sp) addiu $sp,$sp,8 j $31 .end _Z3avgii $LFE2:

Stack during execution of AVG

Saved $fp

Padding (align 8)

Room for x Room for y (arg 2) (arg 3) ...

$sp $sp+4 $sp+8 $sp+12 $sp+16 $fp+4 $fp+8 $fp+12 $fp+16 $fp Old $fp

Code generated by mips-gcc

int avg(int x, int y) { return (x+y)/2; }

C Code Assembly Code

This MIPS compiler points the $fp at the top of the frame and not the bottom (i.e. it will usually match $sp) AVG's frame Caller's frame

slide-24
SLIDE 24

24

Stack Summary

  • Data associated with a subroutine is a

many-to-one relationship (i.e. many instances may be running at the same time). A stack allows for any number of concurrent instances to all have their own storage.

  • Stack always grows towards lower

addresses

  • Stack frames defines organization of data

related to a subroutine

  • A subroutine should leave the stack & $sp

in the same condition it found it

  • $sp and $fp are dedicated registers to

maintaining the system stack

  • Arg. n-1 to 4

(Arg. 0) (Arg. 3) ... Saved regs. ($s0-$s7) Saved $fp Local data m-1 to 0 (also $t0-9) if needed Saved $ra Padding/Empty (Arg. 0) (Arg. 3) ... ...

  • Arg. n-1 to 4
slide-25
SLIDE 25

25

OLD (NOT COVERED IN FALL 2014)

slide-26
SLIDE 26

26

MIPS Register Storage Convention

  • MIPS suggests the following convention for who

is responsible for saving register values onto the stack

– Caller is responsible for

  • Saving any $a0-$a3, $t0-$t9, $v0-$v1 it will need after

the call to the subroutine

  • Stuffing $a0-$a3 with arguments for the “callee”
  • Pushing additional args. for the “callee” on the stack

– Callee is responsible for

  • Saving $ra, $fp, & any $s0-$s7 it uses
  • Allocating space on the stack for its own local vars.
slide-27
SLIDE 27

27

MIPS Register Conventions

Number Name Purpose $0 $zero Constant 0 $1 $at Assembler temporary (psuedo-instrucs.) $2-$3 $v0-$v1 Return value ($v1 only used for dwords) $4-$7 $a0-$a3 Arguments (first 4 of a subroutine) $8-$15, $24,$25 $t0-$t9 Temporary registers $16-$23 $s0-$s7 Saved registers $26-$27 $k0-$k1 Kernel reserved $28 $gp Global pointer (static global data var’s.) $29 $sp Stack pointer $30 $fp Frame pointer $31 $ra Return address

  • Highlighted registers should

be “preserved” across subroutine calls (i.e. the callee must save/restore that register if it needs to use it)

  • Non-highlighted registers

may be overwritten freely by a subroutine

– Thus the caller must save/restore any needed registers before/after calling the routine

slide-28
SLIDE 28

28

Stack Frame Organization

  • Arg. n-1 to 4

(Arg. 0) (Arg. 3) ... Saved regs. ($s0-$s7) Saved $fp Local data m-1 to 0 (also $t0-9) if needed Saved $ra Padding/Empty (Arg. 0) (Arg. 3) ... ...

  • Arg. n-1

downto 4

Main’s Stack Frame

Stack Growth

SUB1’s Stack Frame

  • Args. for SUB1 (or any other routine called by

main)

  • Arg. 0 – 3 are empty since they are passed via

$a0 - $a3. Space is left for them however if they need to be saved when SUB1 calls another routine that needs arguments

  • Space for any local/automatic declared variables in

a routine

  • Space for any “non-preserved” registers that need

to be saved when SUB1 calls another routine

  • Saved $ra / $fp. $ra not needed if leaf procedure
  • Empty slot if needed because local data space

must be double-word aligned (multiple of 8)

  • Space for “preserved registers” that SUB1 will use
  • Args. for any other routine called by SUB1
slide-29
SLIDE 29

29

Example 3 [Not Responsible For]

  • Subroutine to sum an array of integers

int sumit(int data[], int length) { int sum, int i; sum = 0; for(i=0; i < length; i++) sum = sum + data[i]; return sum; }

slide-30
SLIDE 30

30

Example 3 [Not Responsible For]

.text SUMIT: addi $sp,$sp,-32 sw $ra,20($sp) sw $fp,16($sp) addi $fp,$sp,28 sw $zero,-4($fp) # sum = 0; sw $zero,0($fp) # i = 0; LOOP: lw $t0,0($fp) # $t0 = i bge $t0,$a0,FIN # is i < length lw $v0,-4($fp) # $v0 = sum sll $t3,$t0,2 # i = i * 4 add $t3,$a0,$t3 # $t3 = &(data[i]) lw $t4,0($t3) # $t4 = data[i] add $v0,$v0,$t4 # sum += data[i] sw $v0,-4($fp) addi $t0,$t0,1 # i++ sw $t0,0($fp) b LOOP FIN: lw $fp,16($sp) lw $ra,20($sp) addi $sp,$sp,32 jr $ra

Naïve, unoptimized implementation

.text SUMIT: move $v0,$zero # $v0 = sum = 0 LOOP: blez $a1,FIN # check length > 0 lw $t1,0($a0) # $t4 = data[i] add $v0,$v0,$t1 # sum += data[i] addi $a0,$a0,4 # increment ptr. addi $a1,$a1,-1 # length-- b LOOP FIN: jr $ra

Hand-coded assembly implementation

  • r optimized compiler output
slide-31
SLIDE 31

31

Example 3

At start of SUMIT, FP and SP are pointing to stack frame of routine that is calling SUMIT. Argument $a0 is a pointer to a locally declared data array and $a1 is the length (e.g. 100)

.text SUMIT: addi $sp,$sp,-32 sw $ra,20($sp) sw $fp,16($sp) addi $fp,$sp,28 sw $zero,-4($fp) # sum = 0; sw $zero,0($fp) # i = 0; LOOP: lw $t0,0($fp) # $t0 = i bge $t0,$a0,FIN # is i < length lw $v0,-4($fp) # $v0 = sum sll $t3,$t0,2 # i = i * 4 add $t3,$a0,$t3 # $t3 = &(data[i]) lw $t4,0($t3) # $t4 = data[i] add $v0,$v0,$t4 # sum += data[i] sw $v0,-4($fp) addi $t0,$t0,1 # i++ sw $t0,0($fp) b LOOP FIN: lw $fp,16($sp) lw $ra,20($sp) addi $sp,$sp,32 jr $ra

(arg 0) (arg 1) (arg 2) (arg 3) ... data[0] ... data[99]

0x7fffeff8 0x7fffeff4 0x7fffebfc 0x7fffebec 0x7fffebe8 0x7fffebe4 0x7fffebe0 0x7fffebe0 $sp = 0x7fffeff8 $fp =

slide-32
SLIDE 32

32

Example 3

We allocate the stack frame and save the $fp and $ra before adjusting the new $fp.

.text SUMIT: addi $sp,$sp,-32 sw $ra,20($sp) sw $fp,16($sp) addi $fp,$sp,28 sw $zero,-4($fp) # sum = 0; sw $zero,0($fp) # i = 0; LOOP: lw $t0,0($fp) # $t0 = i bge $t0,$a0,FIN # is i < length lw $v0,-4($fp) # $v0 = sum sll $t3,$t0,2 # i = i * 4 add $t3,$a0,$t3 # $t3 = &(data[i]) lw $t4,0($t3) # $t4 = data[i] add $v0,$v0,$t4 # sum += data[i] sw $v0,-4($fp) addi $t0,$t0,1 # i++ sw $t0,0($fp) b LOOP FIN: lw $fp,16($sp) lw $ra,20($sp) addi $sp,$sp,32 jr $ra

(arg 0) (arg 1) (arg 2) (arg 3) 0x7fffeff8 Caller $ra sum i ($a0 = data) ($a1 = length) (arg 2) (arg 3) ... data[0] ... data[99]

0x7fffebec 0x7fffebe8 0x7fffebe4 0x7fffebe0 0x7fffebdc 0x7fffebd8 0x7fffebd4 0x7fffebd0 0x7fffebcc 0x7fffebc8 0x7fffebc4 0x7fffebc0 0x7fffebc0 $sp = 0x7fffebdc $fp = 0x7fffeff8 0x7fffeff4 0x7fffebfc

slide-33
SLIDE 33

33

Example 3

We initialize the local variables i and sum using appropriate displacements from the $fp.

.text SUMIT: addi $sp,$sp,-32 sw $ra,20($sp) sw $fp,16($sp) addi $fp,$sp,28 sw $zero,-4($fp) # sum = 0; sw $zero,0($fp) # i = 0; LOOP: lw $t0,0($fp) # $t0 = i bge $t0,$a0,FIN # is i < length lw $v0,-4($fp) # $v0 = sum sll $t3,$t0,2 # i = i * 4 add $t3,$a0,$t3 # $t3 = &(data[i]) lw $t4,0($t3) # $t4 = data[i] add $v0,$v0,$t4 # sum += data[i] sw $v0,-4($fp) addi $t0,$t0,1 # i++ sw $t0,0($fp) b LOOP FIN: lw $fp,16($sp) lw $ra,20($sp) addi $sp,$sp,32 jr $ra

(arg 0) (arg 1) (arg 2) (arg 3) 0x7fffeff8 Caller $ra sum = 0 i = 0 ($a0 = data) ($a1 = length) (arg 2) (arg 3) ... data[0] ... data[99]

0x7fffebec 0x7fffebe8 0x7fffebe4 0x7fffebe0 0x7fffebdc 0x7fffebd8 0x7fffebd4 0x7fffebd0 0x7fffebcc 0x7fffebc8 0x7fffebc4 0x7fffebc0 0x7fffebc0 $sp = 0x7fffebdc $fp = 0x7fffeff8 0x7fffeff4 0x7fffebfc

slide-34
SLIDE 34

34

Example 3

We run through the loop, length number of times (e.g. 100) updating i and sum each iteration. $t3 acts as a ptr. to the data array allocated in the previous stack frame.

.text SUMIT: addi $sp,$sp,-32 sw $ra,20($sp) sw $fp,16($sp) addi $fp,$sp,28 sw $zero,-4($fp) # sum = 0; sw $zero,0($fp) # i = 0; LOOP: lw $t0,0($fp) # $t0 = i bge $t0,$a0,FIN # is i < length lw $v0,-4($fp) # $v0 = sum sll $t3,$t0,2 # i = i * 4 add $t3,$a0,$t3 # $t3 = &(data[i]) lw $t4,0($t3) # $t4 = data[i] add $v0,$v0,$t4 # sum += data[i] sw $v0,-4($fp) addi $t0,$t0,1 # i++ sw $t0,0($fp) b LOOP FIN: lw $fp,16($sp) lw $ra,20($sp) addi $sp,$sp,32 jr $ra

(arg 0) (arg 1) (arg 2) (arg 3) 0x7fffeff8 Caller $ra sum = Σ(data) i = 100 ($a0 = data) ($a1 = length) (arg 2) (arg 3) ... data[0] ... data[99]

0x7fffebec 0x7fffebe8 0x7fffebe4 0x7fffebe0 0x7fffebdc 0x7fffebd8 0x7fffebd4 0x7fffebd0 0x7fffebcc 0x7fffebc8 0x7fffebc4 0x7fffebc0 0x7fffebc0 $a0 = 0x7fffebdc $fp = 0x7fffebfc- 0x7fffeff8 0x7fffeff8 0x7fffeff4 0x7fffebfc

slide-35
SLIDE 35

35

Example 3

We restore the $fp and $ra, then deallocate the stack frame by resetting the $sp back to its original value.

.text SUMIT: addi $sp,$sp,-32 sw $ra,20($sp) sw $fp,16($sp) addi $fp,$sp,28 sw $zero,-4($fp) # sum = 0; sw $zero,0($fp) # i = 0; LOOP: lw $t0,0($fp) # $t0 = i bge $t0,$a0,FIN # is i < length lw $v0,-4($fp) # $v0 = sum sll $t3,$t0,2 # i = i * 4 add $t3,$a0,$t3 # $t3 = &(data[i]) lw $t4,0($t3) # $t4 = data[i] add $v0,$v0,$t4 # sum += data[i] sw $v0,-4($fp) addi $t0,$t0,1 # i++ sw $t0,0($fp) b LOOP FIN: lw $fp,16($sp) lw $ra,20($sp) addi $sp,$sp,32 jr $ra

(arg 0) (arg 1) (arg 2) (arg 3) 0x7fffeff8 Caller $ra sum = Σ(data) i = 100 ($a0 = data) ($a1 = length) (arg 2) (arg 3) ... data[0] ... data[99]

0x7fffebec 0x7fffebe8 0x7fffebe4 0x7fffebe0 0x7fffebdc 0x7fffebd8 0x7fffebd4 0x7fffebd0 0x7fffebcc 0x7fffebc8 0x7fffebc4 0x7fffebc0 0x7fffebe0 $sp = 0x7fffeff8 $fp = 0x7fffeff8 0x7fffeff4 0x7fffebfc