Sei sulla pagina 1di 25

MIPS Assembly Language

Part F

Dr. Abdallah Mohamed


[Adapted from Computer Organization and Design, 5th Edition, Patterson & Hennessy, 2014, MK]

Reading:

Section 2.8, Appendix A6

Remember: Register Usage


Numb
er
0
1
2-3
4-7
8-15
16-23
24-25
26-27
28
29
30
31

Name

Usage

$zero
$at
$v0 $v1
$a0 $a3
$t0 $t7
$s0 $s7
$t8 $t9
$k0$k1
$gp
$sp
$fp
$ra

constant 0
reserved for assembler
returned values (procedures)
arguments (procedures)
temporary values
saved values
Temporary values (contd)
reserved for operating system
pointer to global area (static data segment)
stack pointer
frame pointer (procedures)
return address (procedures)
3

The Basics
From your previous study (e.g., Java), you know the basics of
procedures (i.e., methods in Java):
Declaration: a procedure has a header, body, and local
variables
Arguments (parameters): a procedure receives argument
values to work with.
Return value: a procedure may return a value to the caller.
Nesting: a procedure may call other procedures.

Examples:

Code That Doesnt Work


So lets try a simple approach
Label both the calling instruction and the procedure, then use
the jump instruction j go to the procedure and return back

do you see the problem?


5

Procedure Call and Return


MIPS uses two instructions to support procedure call and return
Instruction

Example

Meaning

Jump and link

jal label

Save address of next instruction $ra = PC + 4


in $ra, then jump to label
PC = address of label

Jump register

jr

Go to address stored in $ra

$ra

Comment

Now lets try again:

Passing Arguments, Returning Values!


What if we want to pass arguments and return values?
Example:

MIPS Convention #1:


$a0 to $a3 are used to store procedure arguments
$v0 and $v1 are used to store returned values
7

Passing Arguments, Returning Values!, contd


Example1:

What is the
problem
here?

Practice
What is the problems with this MIPS code?

Register Usage
MIPS Convention #2:
$s0 to $s7 are callee-saved registers, i.e., $s0-$s7 should
have the same values before and after the procedure

The caller expects to find these registers unchanged after the call.
Therefore, the callee must save/restore them if they are altered.

$t0 to $t9 are caller-saved registers,


There is no guarantee that the callee will not alter $t0-$t7
The caller must save them if it expects to use them after a call, and then
restore them after the procedure returns.

In summary: by convention, a callee can freely change $t0 to


$t9 but not $s0 to $s7

How to save and restore register values?


Answer: push them into the Stack, and them pull them later.
10

Using the Stack


Stack stores procedure frames

Memory

(activation record)
LIFO (Last In First Out)

$sp points to the last used


space in the stack (the top of
the stack).
It moves downward (by
subtraction) as we add new
data

0x 7FFF FFFF

$fp

Stack

$sp

Dynamic data
(Heap)

$fp points to the first word of


the current procedure frame.
a fixed reference to the
beginning of the procedure
frame (instead of $sp which
may change as we add data)
Not used by all assemblers!

0xFFFF FFFF

$gp

Static data

Size of memory
= 232 bytes
= 230 words
= 4 GB

0x1000 8000
0x1000 0000

PC

Text
(Your code)
Reserved

0x0040 0000
0x0000 0000
11

Using the Stack, contd


The question again: how to save and restore register values
when calling a procedure?

1. PUSH values to stack:


a. Decrement $sp by the amount
required by the saved data
b. Us sw to save data into the
stack. Use $sp as a reference

Memory
0x 7FFF FFFF

Registers
$sp
New Data

2. Do whatever you want with the


registers (alter their values)

3. PULL original values from stack:


a. Use lw to restore original data
from the stack
b. Increment $sp

0x0000 0000
12

Using the Stack, contd


Example3: push / pull two registers $s0 and $s1 to/from the
stack

# 2.
# 3. PULL original values
from stack:
lw
$s0, 4($sp)
lw
$s1, 0($sp)
addi $sp,$sp,8

Memory
Registers

9524

0x 7FFF FFFF

1753

$sp

$s0 76
5

$s1 13
9

13

# 1. PUSH :
addi $sp,$sp,-8
sw
$s0, 4($sp)
sw
$s1, 0($sp)

0x0000 0000

13

Using the Stack, contd


Example 2 (again): fixing the problem with $s0

14

Nested Procedures
A procedure may call another procedure
e.g., A calls B, then B calls C
What could go wrong?
Problems related to $ra
When A calls B, MIPS saves the return address in $ra
When B calls C, the value of $ra is overwritten by new a return address!
Problems related to $a0-$a3
If B calls C with arguments, values of $a0 to $a1 (arguments passed from A
to B) are overwritten by new argument set (arguments passed from B to C).

0x500000

A:

jal B

0x500014
0x500018

B:

jal C

$a0..$a3 have the


wrong values!
jr $ra

C:

jr

$ra

$ra

0x500018
0x500004

$a0

0x12
0x5FA

$a1

0x43
0xC103

$a2

0x15
0xFAC5

$a3

0x30
0x945A
15

Nested Procedures, contd


MIPS Convention #3 (nested procedures):
before calling a nested procedure, caller should save $ra

and
$a0-$a3 in the stack, and it should restore them after returning
from the procedure.

$ra and $a0-$a3 are caller-saved registers

Note that in SPIM, our main is a callee being called by _start


This means the main should also save/restore $ra.
What else does a procedure frame (i.e., space for a procedure
in a stack) includes:
local data (variables)

16

Nested Procedures, contd


Example 2 (again again):
main is called by _start
Since main is called
by _start, it should
also save/restore $ra

17

Local variables
Example 4: local variables

18

Procedure Call: A Summary


Passing parameters via $a0 -$a3
Returned results in $v0, $v1
Local variables stored in a stack procedure frame
main needs its own stack frame (for $ra and its local variables)
Caller-Saved Registers:
$ra
(if calling a nested procedure)
$a0 - $a3
(if calling a nested procedure)
$t0 - $t9
$v0 - $v1
(if calling a nested procedure)
Callee-Saved Registers:
$s0 - $s7
19

Procedure Call: A Summary, contd


main:

jal A

A:

jal B

B:

jal C

C:

Memory
$sp

High address

main frame
A frame

B frame

C frame

Low address
20

Procedure Call: A Summary, contd


Each stack frame should have
enough space allocated to:
The arguments ($a0 to $a3)
The return address ($ra).
Saved registers ($s0 to $s7)
Local data

$fp

$a0 to $a3 (if any)


$ra
$s0 to $s7 (if any)

$sp

Local data

The frame pointer ($fp) points to the


first word of the frame, and $sp
points to the last word.
You dont need to worry about $fp
in this course.

21

Procedure Call: A Summary, contd


A procedure being both a caller and a callee has 3 parts:
Prologue Body - Epilogue

Prologue
(as a callee)
(as a callee)
(as a caller)

Decrease $sp by the framesize


// addi $sp, $sp, -framesize
Save $s0 - $s7 (if will change)
// sw $s?, ?($sp)
Save $ra, $a0 - $a3 (if will change), $t0 - $t9 (if will change) // sw ...

Body
(as a caller)

Do computation
After returning from a nested call, restore if changed and will be used
again: $a0 - $a3 and $t0 - $t9
// lw $?, ?($sp)

Epilogue
(as a callee)
(as a callee)
(as a caller)
(as a callee)
(as a callee)

Put returned results in $v0 - $v1


Restore $s0 - $s7 (if changed)
Restore $ra
Increase $sp by the framesize
jr $ra

// ...
// lw $s?, ?($sp)
// lw $ra, ?($sp)
// addi $sp, $sp, framesize
22

Recursive Procedures
A recursive procedure is the one that conditionally calls itself.
The procedure is thus a caller and callee.

In general, every time a procedure is called a new stack frame


is created for that specific procedure.

In the case of a recursive procedure call, several stack frames


are created, one for each instance of the call.

In the example below, we will have 11 stack frames created for


the recursive call of fact (i.e., for fact(10), fact(9), ,
Memory
fact(1), fact(0))
main frame
fact(10) frame
fact(9) frame

fact(1) frame
fact(0) frame
23

Practice
Translate the function below into MIPS assembly language.
Write a test program for your function. Assume that initially
a = 10, b = 20, c = 5, d = 4

25

Practice
Translate the function below into MIPS code. Write a test
program to compute fact(10)

26

Potrebbero piacerti anche