Translate into MIPS a array of int fori










![The Recursive Case § Let’s examine the recursive step more carefully: return max(array[n-1], rec_max(array, The Recursive Case § Let’s examine the recursive step more carefully: return max(array[n-1], rec_max(array,](https://slidetodoc.com/presentation_image/11033c83b0821fd49d3f51df67143108/image-11.jpg)
- Slides: 11

Translate into MIPS /* a = array of int */ for(i = 0; i < 10; i++) { if(a[i]==a[i+1]) break; } § Try this on your own: /* a = array of int */ for(i = 9; i >= 0; i--) { a[i+1]=a[i]; } a[0] = 0; la addi loop: beq lw lw beq addi j done: $t 0, a $t 1, $t 0, 40 la addi loop: beq lw sw addi j done: sw $t 0, a $t 1, $t 0, 36 $t 0, $t 2, $t 3, $t 2, $t 0, loop $t 1, $t 2, $t 1, loop $t 1, done 0($t 0) 4($t 0) $t 3, done $t 0, 4 $t 0, done -4($t 1) 0($t 1) $t 1, -4 $0, 0($t 1) 1

Control flow in MIPS § MIPS uses the jump-and-link instruction jal to call functions — jal saves the return address (the address of the next instruction) in the dedicated register $ra, before jumping to the function — jal is the only MIPS instruction that can access the value of the program counter, so it can store the return address PC+4 in $ra § To transfer control back to the caller, the function uses a jump-register instruction to the address that was stored in $ra: jr $ra § Arguments to functions can be “passed” by placing them, by convention, in registers $a 0 to $a 3 § Values are returned, by convention, in registers $v 0 and $v 1 2

Warnings and Problems § Assembly language is untyped — there is no distinction between integers, characters, pointers or other kinds of values — You must “type check” your programs — Make sure your function arguments/return values are consistent — No warning if you pass an address of an integer (instead of the integer itself) to a function § A problem: What if a function uses a register that the main program needs after the function call? — Things get really nasty with nested/recursive functions § Solution: spill registers to memory (stack) — save “important” registers to memory before function call — restore these registers after the function call § Who spills? Caller or callee? 3

Who saves the registers? § Argument 1: The caller knows which registers are important to it and should be saved. So caller should save. § Argument 2: The callee knows exactly which registers it will use and potentially overwrite. So callee should save. § Both approaches may wastefully save registers they don’t really need to. § But the caller and callee must not assume anything about each other — may be written by different people or companies — should be able to interface with any caller/callee § Solution: Caller assumes callee will destroy: Callee assumes caller will need: $t 0 -$t 9 $s 0 -$s 7 $a 0 -$a 3 $ra $v 0 -$v 1 4

Example § Consider the following MIPS code: 0 x 7 FFFFFFF stack func: # free to modify $a, $t and $v registers jr $ra main: li $a 0, 7 # set argument for call to func jal func # call func(7) bne $a 0, $v 0, else # test if func(7) == 7 $sp NO!! $a 0 may contain garbage at this point § Since we want to preserve $a 0 across the function call, we must save it before the call, and then restore it after the call. § MIPS stack grows downwards, $sp points to “top” 0 x 0000 5

Pushing elements § To push elements onto the stack: — “Grow stack” by subtracting from $sp — Store the elements into the stack (array) word 1 $sp word 2 § Example: Push $t 1 and $t 2 onto stack addi $sp, -8 sw $t 1, 0($sp) sw $t 2, 4($sp) Before word 1 § Returning to our previous example: li $a 0, 7 addi $sp, -4 sw $a 0, 0($sp) jal func # restore $a 0 bne $a 0, $v 0, else word 2 $t 2 $sp $t 1 After 6

Accessing and popping elements word 1 § You can access any element in the stack (not just the top one) if you know where it is relative to $sp § For example, to retrieve the value of $t 2: lw word 2 $t 2 $sp $t 1 $t 2, 4($sp) § You can pop, or “erase, ” elements simply by adjusting the stack pointer upwards word 1 word 2 § Example: addi $sp, 4 § Note: The “popped” data is still present in memory, but data past the stack pointer is considered invalid $sp $t 2 $t 1 7

Finishing the main example func: # free to modify $a, $t and $v registers jr $ra main: li $a 0, 7 # set argument for call to func addi $sp, -4 # grow stack sw $a 0, 0($sp) # save $a 0 on stack jal func # call func(7) lw $a 0, 0($sp) # restore $a 0 from stack addi $sp, 4 # shrink stack bne $a 0, $v 0, else. . . jr $ra § Unfortunately, main won’t return correctly! — Any time you do a jal, you must save and restore $ra 8

Translate into MIPS int plus. One(int x) { return x + 1; } void main() { int x = 5; x += plus. One(x); } 9

Recursive Functions § Recall that recursive functions have one or more base-cases, and one or more recursive calls. Example: int rec_max(int *array, int n) { if(n == 1) return array[0]; return max(array[n-1], rec_max(array, n-1)); § Useful tip: Translate the base case first (rarely needs the stack) rec_max: # $a 0 = array = &array[0], $a 1 = n bne $a 1, 1, rec_case lw $v 0, 0($a 0) # return-value = array[0] jr $ra rec_case: . . . 10
![The Recursive Case Lets examine the recursive step more carefully return maxarrayn1 recmaxarray The Recursive Case § Let’s examine the recursive step more carefully: return max(array[n-1], rec_max(array,](https://slidetodoc.com/presentation_image/11033c83b0821fd49d3f51df67143108/image-11.jpg)
The Recursive Case § Let’s examine the recursive step more carefully: return max(array[n-1], rec_max(array, n-1)); § Useful tip: Figure out what we need to remember across the recursive function call: array[n-1] ($a 0 = array, $a 1 = n) rec_case: addi $sp, -12 # save space for 3 regs addi $a 1, -1 # compute n-1 sw $a 0, 0($sp) # save &array[0] sw $a 1, 4($sp) # save n-1 sw $ra, 8($sp) # save $ra, since I’m doing jal! jal rec_max # recursive call w/new args # restore $a 0, $a 1 and $ra # compare array[n-1] and $v 0, and put larger into $v 0 11