lecture08 assembly language

28
COMPUTER ORGANIZATION AND ASSEMBLY LANGUAGE Lecture 8 Functions and Recursive function calls in MIPS

Upload: programming-passion

Post on 11-Jul-2015

40 views

Category:

Engineering


1 download

TRANSCRIPT

Page 1: Lecture08 assembly language

COMPUTER ORGANIZATION

AND ASSEMBLY LANGUAGE

Lecture 8

Functions and Recursive function calls in

MIPS

Page 2: Lecture08 assembly language

What have we learned

So far

Write any program in MIPS

Today

More Examples of Function Calls

2

Page 3: Lecture08 assembly language

Steps for Making a Function Call

1) Save necessary values onto stack

2) Assign argument(s), if any

3) jal call

4) Restore values from stack

3

Page 4: Lecture08 assembly language

Structure of a Function

1) Save necessary values onto stack

2) Function body

3) Set return value(s) in $v0 (and $v1), if any

4) Restore values from stack

5) jr $ra

4

Page 5: Lecture08 assembly language

Example Function

sumSquare:

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

lw $ra, 4($sp) # get ret addr

addi $sp,$sp,8 # restore stack

jr $ra

mult: ...

int sumSquare(int x, int y) {

return mult(x,x)+ y;

}

“push”

“pop”

5

Page 6: Lecture08 assembly language

Rules for Function Calls

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

even in functions that only you will call!

6

Page 7: Lecture08 assembly language

Other Registers

$at: may be used by the assembler at any time;

unsafe to use

$k0-$k1: may be used by the OS at any time; unsafe

to use

$gp, $fp: don’t worry about them

Feel free to read up on $gp and $fp in Appendix A, but you

can write perfectly good MIPS code without them.

7

Page 8: Lecture08 assembly language

Basic Structure of a Function

entry_label:addi $sp,$sp, -framesizesw $ra, framesize-4($sp) # save $rasave other regs if need be

...

restore other regs if need belw $ra, framesize-4($sp) # restore $raaddi $sp,$sp, framesizejr $ra

Epilogue

Prologue

Body (call other functions…)

ra

memory

8

Page 9: Lecture08 assembly language

Register Conventions – Saved Registers

$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!

9

Page 10: Lecture08 assembly language

Register Conventions – Volatile

Registers

$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.

10

Page 11: Lecture08 assembly language

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.

11

Page 12: Lecture08 assembly language

Requirements for Functions

Pass arguments to the function

$a0, $a1, $a2, $a3

Get results from the function

$v0, $v1

Can call from anywhere

jal

Can always return back

jr

Nested and Recursive Functions

Save $ra on stack

Saving and Restoring Registers

Register Conventions

Functions with more than 4 parameters

Pass them on the stack

12

Page 13: Lecture08 assembly language

Nested Procedures

Leaf procedures do not call other procedures.

What happens to return addresses with nested procedures?

int rt_1 (int i) {

if (i == 0) return 0;

elsereturn rt_2(i-1);

}

caller: jal rt_1

next: . . .

rt_1: bne $a0, $zero, to_2add $v0, $zero, $zerojr $ra

to_2: addi $a0, $a0, -1jal rt_2jr $ra

rt_2: . . .

13

Page 14: Lecture08 assembly language

Nested Procedures Outcome

caller: jal rt_1next: . . .

rt_1: bne $a0, $zero, to_2add $v0, $zero, $zerojr $ra

to_2: addi $a0, $a0, -1jal rt_2jr $ra

rt_2: . . .

• On the call to rt_1, the return address (next in the caller routine) gets stored in $ra. What happens to the value in $ra (when i != 0) when rt_1 makes a call to rt_2?

int rt_1 (int i)

{

if (i == 0)

return 0;

else

return rt_2(i-1);

}

14

Page 15: Lecture08 assembly language

caller rt addr

caller rt addr

Saving the Return Address, Part

1Nested procedures (i passed in $a0, return value in $v0)

high addr

$sp

low addr

$a0 value

$rart_2

old TOS

rt_1: bne $a0, $zero, to_2

add $v0, $zero, $zero

jr $ra

to_2: addi $sp, $sp, -8

sw $ra, 4($sp)

sw $a0, 0($sp)

addi $a0, $a0, -1

jal rt_2

rt_2: lw $a0, 0($sp)

lw $ra, 4($sp)

addi $sp, $sp, 8

jr $ra

• Save the return address (and arguments) on the stack

int rt_1 (int i)

{

if (i == 0)

return 0;

else

return rt_2(i-1);

}

$a0

$rt_2 $a0 value

$a0 value $a0 value - 1

15

Page 16: Lecture08 assembly language

Compiling a Recursive Procedure

Calculating factorial:int fact (int n) {if (n < 1) return 1;else return (n * fact (n-1));

}

Recursive procedure (one that calls itself!)

fact (0) = 1

fact (1) = 1 * 1 = 1

fact (2) = 2 * 1 * 1 = 2

fact (3) = 3 * 2 * 1 * 1 = 6

fact (4) = 4 * 3 * 2 * 1 * 1 = 24

. . .

Assume n is passed in $a0; result returned in $v0

16

Page 17: Lecture08 assembly language

Compiling a Recursive Procedure

fact: addi $sp, $sp, -8 #adjust stack pointer

sw $ra, 4($sp) #save return address

sw $a0, 0($sp) #save argument n

slt $t0, $a0, 1 #test for n < 1

beq $t0, $zero, L1 #if n >=1, go to L1

addi $v0, $zero, 1 #else return 1 in $v0

addi $sp, $sp, 8 #adjust stack pointer

jr $ra #return to caller

L1: addi $a0, $a0, -1 #n >=1, so decrement n

jal fact #call fact with (n-1)

#this is where fact returns

bk_f: lw $a0, 0($sp) #restore argument n

lw $ra, 4($sp) #restore return address

addi $sp, $sp, 8 #adjust stack pointer

mul $v0, $a0, $v0 #$v0 = n * fact(n-1)

jr $ra #return to caller

int fact (int n)

{

if (n < 1)

return 1;

else

return (n * fact (n-1));

}

17

Page 18: Lecture08 assembly language

1

caller rt addr

caller rt addr

A Look at the Stack for $a0 =

2 $sp

$ra

$a0

$v0

$a0 = 2

2

bk_f

old TOS

int fact (int n)

{

if (n < 1)

return 1;

else

return (n * fact (n-1));

}

fact: addi $sp, $sp, -8

sw $ra, 4($sp)

sw $a0, 0($sp)

slt $t0, $a0, 1

beq $t0, $zero, L1

addi $v0, $zero, 1

addi $sp, $sp, 8

jr $ra

L1: addi $a0, $a0, -1

jal fact

bk_f: lw $a0, 0($sp)

lw $ra, 4($sp)

addi $sp, $sp, 8

mul $v0, $a0, $v0

jr $ra

18

Page 19: Lecture08 assembly language

1

caller rt addr

A Look at the Stack for $a0 =

2

$sp

$ra

$a0

$v0

$a0 = 2

bk_f

old TOS

• Stack state after execution of first encounter with the jalinstruction (second call to fact routine with $a0 now holding 1)– saved return address to caller

routine (i.e., location in the main routine where first call to fact is made) on the stack

– saved original value of $a0 on the stack

int fact (int n)

{

if (n < 1)

return 1;

else

return (n * fact (n-1));

}

19

Page 20: Lecture08 assembly language

1

bk_f

A Look at the Stack for $a0 =

2

$sp

$ra

$a0

$v0

$a0 = 1

0

bk_f

old TOS

int fact (int n)

{

if (n < 1)

return 1;

else

return (n * fact (n-1));

}

caller rt addr

$a0 = 2fact: addi $sp, $sp, -8

sw $ra, 4($sp)

sw $a0, 0($sp)

slt $t0, $a0, 1

beq $t0, $zero, L1

addi $v0, $zero, 1

addi $sp, $sp, 8

jr $ra

L1: addi $a0, $a0, -1

jal fact

bk_f: lw $a0, 0($sp)

lw $ra, 4($sp)

addi $sp, $sp, 8

mul $v0, $a0, $v0

jr $ra

20

Page 21: Lecture08 assembly language

caller rt addr

A Look at the Stack for $a0 =

2

$ra

$a0

$v0

$a0 = 2

0

bk_f

old TOS

$sp$a0 = 1

bk_f

bk_f

• Stack state after execution of second encounter with the jal instruction (third call to fact routine with $a0 now holding 0)– saved return address of

instruction in caller routine (instruction after jal) on the stack

– saved previous value of $a0on the stack

int fact (int n)

{

if (n < 1)

return 1;

else

return (n * fact (n-1));

}

21

Page 22: Lecture08 assembly language

1

bk_f

A Look at the Stack for $a0 =

2

$sp

$ra

$a0

$v0

$a0 = 1

0

bk_f

old TOS

int fact (int n)

{

if (n < 1)

return 1;

else

return (n * fact (n-1));

}

caller rt addr

$a0 = 2fact: addi $sp, $sp, -8

sw $ra, 4($sp)

sw $a0, 0($sp)

slt $t0, $a0, 1

beq $t0, $zero, L1

addi $v0, $zero, 1

addi $sp, $sp, 8

jr $ra

L1: addi $a0, $a0, -1

jal fact

bk_f: lw $a0, 0($sp)

lw $ra, 4($sp)

addi $sp, $sp, 8

mul $v0, $a0, $v0

jr $ra

bk_f

$a0 = 0

22

Page 23: Lecture08 assembly language

1

bk_f

A Look at the Stack for $a0 =

2

$sp

$ra

$a0

$v0

$a0 = 1

0

bk_f

old TOS

int fact (int n)

{

if (n < 1)

return 1;

else

return (n * fact (n-1));

}

caller rt addr

$a0 = 2 • Stack state after execution of first encounter with the first jr instruction ($v0initialized to 1)– stack pointer updated to

point to third call to fact

23

Page 24: Lecture08 assembly language

1

A Look at the Stack for $a0 =

2

$sp

$ra

$a0

$v0

0

bk_f

old TOS

int fact (int n)

{

if (n < 1)

return 1;

else

return (n * fact (n-1));

}

caller rt addr

$a0 = 2fact: addi $sp, $sp, -8

sw $ra, 4($sp)

sw $a0, 0($sp)

slt $t0, $a0, 1

beq $t0, $zero, L1

addi $v0, $zero, 1

addi $sp, $sp, 8

jr $ra

L1: addi $a0, $a0, -1

jal fact

bk_f: lw $a0, 0($sp)

lw $ra, 4($sp)

addi $sp, $sp, 8

mul $v0, $a0, $v0

jr $ra

bk_f

$a0 = 1

1

1*1 = 1

24

Page 25: Lecture08 assembly language

A Look at the Stack for $a0 =

2

$sp

$ra

$a0

$v0

bk_f

old TOS

int fact (int n)

{

if (n < 1)

return 1;

else

return (n * fact (n-1));

}

caller rt addr

$a0 = 2

1

1

• Stack state after execution of first encounter with the second jr instruction (return from fact routine after updating $v0 to 1 * 1)

– return address to caller routine (bk_f in fact routine) restored to $ra from the stack

– previous value of $a0restored from the stack

– stack pointer updated to point to second call to fact

25

Page 26: Lecture08 assembly language

1

A Look at the Stack for $a0 =

2

$sp

$ra

$a0

$v0

1

bk_f

old TOS

int fact (int n)

{

if (n < 1)

return 1;

else

return (n * fact (n-1));

}

caller rt addr

$a0 = 2fact: addi $sp, $sp, -8

sw $ra, 4($sp)

sw $a0, 0($sp)

slt $t0, $a0, 1

beq $t0, $zero, L1

addi $v0, $zero, 1

addi $sp, $sp, 8

jr $ra

L1: addi $a0, $a0, -1

jal fact

bk_f: lw $a0, 0($sp)

lw $ra, 4($sp)

addi $sp, $sp, 8

mul $v0, $a0, $v0

jr $ra

2

2*1 = 2

caller rt addr

26

Page 27: Lecture08 assembly language

A Look at the Stack for $a0 =

2 $sp

$ra

$a0

$v0

old TOS

2

2

caller rt addr

• Stack state after execution of second encounter with the second jr instruction (return from fact routine after updating $v0 to 1 * 1 * 2)

– return address to caller routine (main routine) restored to $rafrom the stack

– original value of $a0 restored from the stack

– stack pointer updated to point to first call to fact

int fact (int n)

{

if (n < 1)

return 1;

else

return (n * fact (n-1));

}

27

Page 28: Lecture08 assembly language

Summary

Requirements for functions

Register Conventions

Nested function calls

Recursive function calls

28