- Monday, March 11 (11:59pm)
Homework can submitted via email or printout by deadline.
Patterson & Hennessy. Chapter 3 (through Section 3.7)
(Questions 2-4 below require knowledge of Section 3.7)
On Slide 12 of last week's lecture I claimed that there was an instruction SUBI, which subtracted immediate values. That isn't strictly true. In order to subtract an immediate value in MIPS, one uses ADDI with a negative immediate value. Thussubi $sp, $sp, 8 # reserve two words on the stackis more accurately written:addi $sp, $sp, -8 # reserve two words on the stack
The important thing to remember in writing FIB is that you need to protect some data by pushing it onto the stack. The recursive calls will wipe out any register values you are liable to care about.
FIB: addi $t0, $zero, 1 # $t0 = 1 beq $a0, $zero, BASE0 # fib(0) case beq $a0, $t0, BASE1 # fib(1) case addi $sp, $sp, -12 # allocate 3 slots on stack sw $ra, 0($sp) # store return address sw $a0, 4($sp) # store n ($a0) # third entry saved till later addi $a0, $a0, -1 jal FIB # fib(n-1) sw $v0, 8($sp) # store result on stack lw $a0, 4($sp) # restore n ($a0) addi $a0, $a0, -2 jal FIB # fib(n-2) lw $t1, 8($sp) # load and add $v0, $v0, $t1 # add in fib(n-1) lw $ra, 0($sp) # restore return address addi $sp, $sp, 12 # free stack frame jr $ra # return BASE0: add $v0, $zero, $zero # fib(0) = 0 jr $ra # return BASE1: addi $v0, $zero, 1 # fib(1) = 1 jr $ra # return
| A | b | y | t | e | i | s | 8 | b | i | t | s | |||||
| 65 | 32 | 98 | 121 | 116 | 101 | 32 | 105 | 115 | 32 | 56 | 32 | 98 | 105 | 116 | 115 | 0 |
| A | b | y | t | e | i | s | 8 | b | i | t | s | |||||
| 0x41 | 0x20 | 0x62 | 0x79 | 0x74 | 0x65 | 0x20 | 0x69 | 0x73 | 0x20 | 0x38 | 0x20 | 0x62 | 0x69 | 0x74 | 0x73 | 0x00 |
The basic idea: Read a character (register $t0), if it is a digit, convert it to its numerical value by subtracting 48, and add it to the subtotal (register $v0). Then, if there's another character coming, multiply by 10.
A2D: add $v0, $zero, $zero # accumulating result addi $t1, $zero, 48 # $t1 = 48 (ascii '0') addi $t2, $zero, 58 # $t2 = 58 (ascii '9' + 1) lb $t0, 0($a0) # $t0 = first byte/char beq $t0, $zero, DONE # termination character? LOOP: slt $t4, $t0, $t1 # range test ($t0 < '0') bne $t4, $zero, BADDATA slt $t4, $t0, $t2 # range test ($t0 =< '9') beq $t4, $zero, BADDATA sub $t0, $t0, $t1 # convert from digit to value add $v0, $v0, $t0 # add to subtotal addi $a0, $a0, 1 # advance cursor lb $t0, 0($a0) # $t0 = next char beq $t0, $zero, DONE # termination character? # another digit coming, multiply by 10 add $v0, $v0, $v0 # $v0 = 2 x $v0 add $t5, $v0, $v0 # $t5 = 4 x $v0 add $v0, $v0, $t5 # $v0 = (2+4) x $v0 add $v0, $v0, $t5 # $v0 = (2+4+4) x $v0 j LOOP # process next digit BADDATA: addi $v0, $zero, -1 # illegal input, return -1 DONE: jr $ra