Upload
alvaro-merrill
View
216
Download
0
Embed Size (px)
Citation preview
CCMMLLCCMMLL
CS 230: Computer CS 230: Computer Organization and Organization and
Assembly LanguageAssembly LanguageAviral
ShrivastavaDepartment of Computer Science and
EngineeringSchool of Computing and Informatics
Arizona State University
Slides courtesy: Prof. Yann Hang Lee, ASU, Prof. Mary Jane Irwin, PSU, Ande Carle, UCB
CCMMLLCCMMLL
AnnouncementsAnnouncements
CCMMLLCCMMLL
What have we learnedWhat have we learned
• So far– Write any program in MIPS
• Today– More Examples of Function Calls
CCMMLLCCMMLL
High-level language program (in C) swap (int v[], int k) . . .
Assembly language program (for MIPS) swap: sll $2, $5, 2 add $2, $4, $2 lw $15, 0($2) lw $16, 4($2) sw $16, 0($2) sw $15, 4($2) jr $31
Machine (object) code (for MIPS) 000000 00000 00101 0001000010000000 000000 00100 00010 0001000000100000 100011 00010 01111 0000000000000000 100011 00010 10000 0000000000000100 101011 00010 10000 0000000000000000 101011 00010 01111 0000000000000100 000000 11111 00000 0000000000001000
Below the Below the ProgramProgram
C - Compiler
Assembler
CCMMLL
MIPS Instructions, so MIPS Instructions, so farfar
Category Instr Op Code Example Meaning
Arithmetic(R format)
add 0 and 32 add $s1, $s2, $s3 $s1 = $s2 + $s3
subtract 0 and 34 sub $s1, $s2, $s3 $s1 = $s2 - $s3
Datatransfer(I format)
load word 35 lw $s1, 100($s2) $s1 = Memory($s2+100)
store word 43 sw $s1, 100($s2) Memory($s2+100) = $s1
load byte 32 lb $s1, 101($s2) $s1 = Memory($s2+101)
store byte 40 sb $s1, 101($s2) Memory($s2+101) = $s1
Cond. Branch
br on equal 4 beq $s1, $s2, L if ($s1==$s2) go to L
br on not equal 5 bne $s1, $s2, L if ($s1 !=$s2) go to L
set on less than 0 and 42 slt $s1, $s2, $s3 if ($s2<$s3) $s1=1 else $s1=0
Uncond. Jump
jump 2 j 2500 go to 10000
jump register 0 and 8 jr $t1 go to $t1
jump and link 3 jal 2500 go to 10000; $ra=PC+4
CCMMLLCCMMLL
3232
32
read data
32 3232
32
3232
32
32
32
5
5
5
32
15
MIPS OrganizationMIPS OrganizationProcessor
Memory
32 bits
230
words
read/write addr
write data
word address(binary)
0…00000…01000…10000…1100
1…1100Register File
src1 addr
src2 addr
dst addr
write data
32 bits
src1data
src2data
32registers
($zero - $ra)
32
32PC
ALU 0 2 3764
byte address(big Endian)
FetchPC = PC+4
DecodeExec
Add
4
Addbr offset
CCMMLLCCMMLL
MIPS MIPS R3000 R3000
ISAISA• Instruction Categories
– Arithmetic – Load/Store– Jump and Branch– Floating Point
• coprocessor
– Memory Management– Special
R0 - R31
PC
HI
LO
OP
OP
OP
rs rt rd sa funct
rs rt immediate
Registers
R Format
I Format
6 bits 5 bits 5 bits 5 bits 5 bits 6 bits
• 3 Instruction Formats: all 32 bits wide
6 bits 5 bits 5 bits 16 bits
J Format6 bits 26 bits
jump target
CCMMLLCCMMLL
Programming StylesProgramming Styles
• Procedures (subroutines) allow the programmer to structure programs making them– easier to understand and debug and– allowing code to be reused
• Procedures allow the programmer to concentrate on one portion of the code at a time– parameters act as barriers between the procedure and
the rest of the program and data, allowing the procedure to be passed values (arguments) and to return values (results)
CCMMLLCCMMLL
Requirements for Requirements for FunctionsFunctions
• 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• Functions with more than 4 parameters
CCMMLLCCMMLL
Steps for Making a Function Steps for Making a Function CallCall
1) Save necessary values onto stack
2) Assign argument(s), if any
3) jal call
4) Restore values from stack
CCMMLLCCMMLL
Example FunctionExample Function
sumSquare:addi $sp,$sp,-8 # space on stacksw $ra, 4($sp) # save ret addrsw $a1, 0($sp) # save y
add $a1,$a0,$zero # mult(x,x)jal mult # call mult
lw $a1, 0($sp) # restore yadd $v0,$v0,$a1 # mult()+ylw $ra, 4($sp) # get ret addraddi $sp,$sp,8 # restore stack jr $ra
mult: ...
int sumSquare(int x, int y) {
return mult(x,x)+ y;
}
“push”
“pop”
CCMMLLCCMMLL
Rules for Function CallsRules 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!
CCMMLLCCMMLL
Other RegistersOther 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.
CCMMLLCCMMLL
Basic Structure of a Basic Structure of a FunctionFunction
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, framesize jr $ra
Epilogue
Prologue
Body (call other functions…)
ra
memory
CCMMLLCCMMLL
Register ConventionsRegister Conventions
• CalleR: the calling function• CalleE: the function being called
• When callee returns from executing, the caller needs to know which registers may have changed and which are guaranteed to be unchanged.
• 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.
CCMMLLCCMMLL
Register ConventionsRegister Conventions
• None guaranteed inefficient– Caller will be saving lots of regs that callee doesn’t
use!
• All guaranteed inefficient – Callee will be saving lots of regs that caller doesn’t
use!
• Register convention: A balance between the two.
CCMMLLCCMMLL
Register Conventions – Register Conventions – Saved Saved RegistersRegisters
• $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!
CCMMLLCCMMLL
Register Conventions – Register Conventions – Volatile Volatile RegistersRegisters
• $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.
CCMMLL
MIPS Register MIPS Register ConventionConvention
Name Register Number
Usage Should preserve on
call?
$zero 0 the constant 0 n.a.
$v0 - $v1 2-3 returned values no
$a0 - $a3 4-7 arguments yes
$t0 - $t7 8-15 temporaries no
$s0 - $s7 16-23 saved values yes
$t8 - $t9 24-25 temporaries no
$gp 28 global pointer yes
$sp 29 stack pointer yes
$fp 30 frame pointer yes
$ra 31 return address yes
CCMMLLCCMMLL
Register ConventionsRegister 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.
CCMMLLCCMMLL
Requirements for Requirements for FunctionsFunctions
• 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
CCMMLLCCMMLL
Nested ProceduresNested 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: . . .
CCMMLLCCMMLL
Nested Procedures Nested Procedures OutcomeOutcome
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); }
CCMMLLCCMMLL
caller rt addr
caller rt addr
Saving the Return Saving the Return Address, Part 1Address, Part 1
Nested procedures (i passed in $a0, return value in $v0)
high addr
$sp
low addr
$a0 value
$rabk_2
old TOS
rt_1: bne $a0, $zero, to_2
add $v0, $zero, $zero
jr $rato_2: addi $sp, $sp, -8
sw $ra, 4($sp)sw $a0, 0($sp)addi $a0, $a0, -1jal rt_2
bk_2: lw $a0, 0($sp)lw $ra, 4($sp)addi $sp, $sp, 8jr $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
CCMMLLCCMMLL
Compiling a Recursive Compiling a Recursive ProcedureProcedure
• 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) = 1fact (1) = 1 * 1 = 1fact (2) = 2 * 1 * 1 = 2fact (3) = 3 * 2 * 1 * 1 = 6fact (4) = 4 * 3 * 2 * 1 * 1 = 24. . .
• Assume n is passed in $a0; result returned in $v0
CCMMLLCCMMLL
Compiling a Recursive Compiling a Recursive ProcedureProcedure
fact: addi $sp, $sp, -8 #adjust stack pointersw $ra, 4($sp) #save return addresssw $a0, 0($sp) #save argument nslt $t0, $a0, 1 #test for n < 1beq $t0, $zero, L1 #if n >=1, go to L1addi $v0, $zero, 1 #else return 1 in $v0addi $sp, $sp, 8 #adjust stack pointerjr $ra #return to caller
L1: addi $a0, $a0, -1 #n >=1, so decrement njal fact #call fact with (n-1)
#this is where fact returnsbk_f: lw $a0, 0($sp) #restore argument n
lw $ra, 4($sp) #restore return address
addi $sp, $sp, 8 #adjust stack pointermul $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)); }
CCMMLL
1
caller rt addr
caller rt addr
A Look at the Stack for A Look at the Stack for $a0 = 2$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, -8sw $ra, 4($sp)sw $a0, 0($sp)slt $t0, $a0, 1beq $t0, $zero,
L1addi $v0, $zero,
1addi $sp, $sp, 8jr $ra
L1: addi $a0, $a0, -1jal fact
bk_f: lw $a0, 0($sp)lw $ra, 4($sp)addi $sp, $sp, 8mul $v0, $a0,
$v0jr $ra
CCMMLL
1
caller rt addr
A Look at the Stack for A Look at the Stack for $a0 = 2$a0 = 2
$sp
$ra
$a0
$v0
$a0 = 2
bk_f
old TOS
• Stack state after execution of first encounter with the jal instruction (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)); }
CCMMLL
1
bk_f
A Look at the Stack for A Look at the Stack for $a0 = 2$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, 1beq $t0, $zero,
L1addi $v0, $zero,
1addi $sp, $sp, 8jr $ra
L1: addi $a0, $a0, -1jal fact
bk_f: lw $a0, 0($sp)lw $ra, 4($sp)addi $sp, $sp, 8mul $v0, $a0,
$v0jr $ra
CCMMLL
caller rt addr
A Look at the Stack for A Look at the Stack for $a0 = 2$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 $a0 on the stack
int fact (int n) { if (n < 1) return 1; else return (n * fact (n-1)); }
CCMMLL1
bk_f
A Look at the Stack for A Look at the Stack for $a0 = 2$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, 1beq $t0, $zero,
L1addi $v0, $zero,
1addi $sp, $sp, 8jr $ra
L1: addi $a0, $a0, -1jal fact
bk_f: lw $a0, 0($sp)lw $ra, 4($sp)addi $sp, $sp, 8mul $v0, $a0,
$v0jr $ra
bk_f
$a0 = 0
CCMMLL1
bk_f
A Look at the Stack for A Look at the Stack for $a0 = 2$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 ($v0 initialized to 1)– stack pointer updated
to point to third call to fact
CCMMLL1
A Look at the Stack for A Look at the Stack for $a0 = 2$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, 1beq $t0, $zero,
L1addi $v0, $zero,
1addi $sp, $sp, 8jr $ra
L1: addi $a0, $a0, -1jal fact
bk_f: lw $a0, 0($sp)lw $ra, 4($sp)addi $sp, $sp, 8mul $v0, $a0,
$v0jr $ra
bk_f
$a0 = 1
1
1*1 = 1
CCMMLL
A Look at the Stack for A Look at the Stack for $a0 = 2$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 $a0 restored from the stack
– stack pointer updated to point to second call to fact
CCMMLL1
A Look at the Stack for A Look at the Stack for $a0 = 2$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, 1beq $t0, $zero,
L1addi $v0, $zero,
1addi $sp, $sp, 8jr $ra
L1: addi $a0, $a0, -1jal fact
bk_f: lw $a0, 0($sp)lw $ra, 4($sp)addi $sp, $sp, 8mul $v0, $a0,
$v0jr $ra
2
2*1 = 2
caller rt addr
CCMMLL
A Look at the Stack for A Look at the Stack for $a0 = 2$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 $ra from 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)); }
CCMMLL
MIPS Register MIPS Register ConventionConvention
Name Register Number
Usage Should preserve on
call?
$zero 0 the constant 0 n.a.
$v0 - $v1 2-3 returned values no
$a0 - $a3 4-7 arguments yes
$t0 - $t7 8-15 temporaries no
$s0 - $s7 16-23 saved values yes
$t8 - $t9 24-25 temporaries no
$gp 28 global pointer yes
$sp 29 stack pointer yes
$fp 30 frame pointer yes
$ra 31 return address yes
CCMMLL
MIPS InstructionsMIPS Instructions
Category Instr Op Code Example Meaning
Arithmetic(R format)
add 0 and 32 add $s1, $s2, $s3 $s1 = $s2 + $s3
subtract 0 and 34 sub $s1, $s2, $s3 $s1 = $s2 - $s3
Datatransfer(I format)
load word 35 lw $s1, 100($s2) $s1 = Memory($s2+100)
store word 43 sw $s1, 100($s2) Memory($s2+100) = $s1
load byte 32 lb $s1, 101($s2) $s1 = Memory($s2+101)
store byte 40 sb $s1, 101($s2) Memory($s2+101) = $s1
Cond. Branch
br on equal 4 beq $s1, $s2, L if ($s1==$s2) go to L
br on not equal 5 bne $s1, $s2, L if ($s1 !=$s2) go to L
set on less than 0 and 42 slt $s1, $s2, $s3 if ($s2<$s3) $s1=1 else $s1=0
Uncond. Jump
jump 2 j 2500 go to 10000
jump register 0 and 8 jr $t1 go to $t1
jump and link 3 jal 2500 go to 10000; $ra=PC+4
CCMMLLCCMMLL
Yoda says…Yoda says…
• Do or do not... there is no try