310 likes | 403 Vues
Dive into the Fibonacci procedure in MIPS assembly language, learning how to calculate Fibonacci numbers recursively and efficiently. Understand register usage and the stack functionality for proper execution.
E N D
Assembly Language IICPSC 321 Andreas Klappenecker
Administrative Issues • Confusion about Section 502 • Your lab assignments should be turned in during your lab. • Take advantage of the Teaching Assistant and the Peer Teacher. • Learn about many computer related topics during the workshops offered by our graduate students. • Go to seminars to learn about current trends in computer science.
The Story so far… • We introduced numerous MIPS assembly language instructions. • We are now familiar with registers and register usage conventions. • We know how to use system calls, basic I/O • We have learned how the stack works • What is missing? Practice! Practice! Practice!
Stack $sp = $sp - 12 The stack pointer is contained in register $sp. The stack grows from above. If you want to push a word onto the stack: $sp = $sp – 4 Efficiency: If you want to push 3 registers onto the stack, subtract 12! high address stack pointer$sp -> low address
Fibonacci Procedure • We want to write a recursive procedure fib that performs the following calculation: • If n=0 or n=1, then f(0)=0 and f(1)=1 • simply return the argument • If n>1, then f(n)=f(n-1)+f(n-2) • recursively call fib
Top Down Design <<Fibonacci>>= fib: <<save registers>> <<calculation>> <<restore registers>> We assume that $a0 contains the argument n, register $v0 the result, and $s0 some intermediate result.
Calculation <<calculation>>= bgt $a0,1, gen # if n>1, goto generic case move $v0,$a0 # output = input if n=0 or n=1 j rreg # goto restore registers gen: sub $a0,$a0,1 # param = n-1 jal fib # compute fib(n-1) move $s0,$v0 # save fib(n-1) sub $a0,$a0,1 # set param to n-2 jal fib # and make recursive call add $v0, $v0, $s0 # $v0 = fib(n-2)+fib(n-1)
<<save registers>>= subi $sp,$sp,12 sw $a0, 0($sp) sw $s0, 4($sp) sw $ra, 8($sp) <<restore registers>>= lw $a0, 0($sp) lw $s0, 4($sp) lw $ra, 8($sp) addi $sp,$sp, 12 jr $ra Save and Restore Registers
fib: sub $sp,$sp,12 # save registers on stack sw $a0, 0($sp) # save $a0 = n sw $s0, 4($sp) # save $s0 sw $ra, 8($sp) # save return address $ra bgt $a0,1, gen # if n>1 then goto generic case move $v0,$a0 # output = input if n=0 or n=1 j rreg # goto restore registers gen: sub $a0,$a0,1 # param = n-1 jal fib # compute fib(n-1) move $s0,$v0 # save fib(n-1) sub $a0,$a0,1 # set param to n-2 jal fib # and make recursive call add $v0, $v0, $s0 # $v0 = fib(n-2)+fib(n-1) rreg: lw $a0, 0($sp) # restore registers from stack lw $s0, 4($sp) # lw $ra, 8($sp) # add $sp, $sp, 12 # decrease the stack size jr $ra
Quiz • How do you calculate f(12) with the Fibonacci procedure that we have written? li $a0, 12 jal fib
Short Discussion • You are now familiar with the basics of the MIPS assembly language. • Start experimenting! Do it yourself! • What kind of techniques do you use to design your programs? • What style of documentation are you using? • Are you familiar with TeX or LaTeX?
What Next? • We need a more detailed knowledge about the instruction formats to fully appreciate certain restrictions. • The functional interface is easy to understand, since it is basically familiar procedural programming • We need to understand how the computer interprets the instruction, so that we can transition to the discussion of the MIPS hardware architecture
Machine Language What does that mean? • Machine language level programming means that we have to provide the bit encodings for the instructions • For example, add $t0, $s1, $s2 represents the 32bit string • 00000010001100100100000000100000 • Assembly language mnemonics usually translate into one instruction • We also have pseudo-instructions that translate into several instructions
Instruction Word Formats Register format Immediate format Jump format op-code rs rt rd shamt funct 6 5 5 5 5 6 op-code rs rt immediate value 6 5 5 16 op-code 26 bit current segment address 6 26
Register Format (R-Format) Register format op: basic operation of instruction funct: variant of instruction rs: first register source operand rt: second register source operand rd: register destination operand shamt: shift amount op-code rs rt rd shamt funct 6 5 5 5 5 6
Watson, the case is clear… • add $t0, $s1, $s2 • 00000010001100100100000000100000 • 000000 10001 10010 01000 00000 100000 • Operation and function field tell the computer to perform an addition • 000000 10001 10010 01000 00000 100000 • registers $17, $18 and $8 op-code rs rt rd shamt funct 6 5 5 5 5 6
Number Value Name Registers return values from functions pass parameters to functions $t0-$t7 are caller saved registers – use these registers in functions $s0-$s7 are callee-saved registers – use these registers for values that must be maintained across function calls.
Watson, the case is clear… • add $t0, $s1, $s2 • 00000010001100100100000000100000 • 000000 10001 10010 01000 00000 100000 • source registers $s1=$17 and $s2=$18 and target register $t0=$8 op-code rs rt rd shamt funct 6 5 5 5 5 6
R-Format Example Register format (op, funct)=(0,32): add rs=17: first source operand is $s1 rt=18: second source operand is $s2 Rd=8: register destination is $t0 add $t0, $s1, $s2 0 17 18 8 0 32 6 5 5 5 5 6
Immediate Format (I-Format) Immediate format op determines the instruction (op <> 0) rs is the source register rt is the destination register 16bit immediate value op rs rt immediate value 6 5 5 16
I-Format Example Immediate format op=8 means addi rs=29 means source register is $sp rt=29 means $sp is destination register immediate value = 4 addi $sp, $sp, 4 8 29 29 4 6 5 5 16
Problem • The MIPS assembly language has the command andi, an immediate bit-wise and operation • We can say li $s0, 0xCDEF1234 to load register $s0 with the content 0xCDEF1234 • Why is this strange? • In the immediate format, you can only load 16 bits, but the constant is 32 bits!
Pseudo-Instructions • li $s0, 0xCDEF1234 is a pseudo-instruction • It is a convenient shorthand for lui $at, 0xCDEF ori $s0, $at, 0x1234 • The register $at is used here by the assembler; this is the reason why you should not use this register.
Puzzle • How can we swap the content of two registers, say $s0 and $s1, without accessing other registers or memory? • Solution: xor $s0, $s0, $s1 xor $s1, $s0, $s1 xor $s0, $s0, $s1
MIPS Addressing Modes • Immediate addressing • Register addressing • Base displacement addressing • PC-relative addressing • address is the sum of the PC and a constant in the instruction • Pseudo-direct addressing • jump address is 26bits of instruction concatenated with upper bits of PC
Addressing Modes • Register Addressing • add $s1, $s2, $s3 • $s1 = $s2 + $s3 • Immediate Addressing • addi $s1, $s2, 100 • $s1 = $s2 + 100
Addressing Modes • Base addressing • lw $s1, 100($s2) • $s1 = Memory[$s2+100] • PC-relative branch • beq $s1, $s2, 25 • if ($s1 == $s2) goto PC + 4 + 100
Addressing Modes • Pseudo-direct addressing • j 1000 • goto 1000 • concatenate 26bit address with upper bits of the PC • Study section 3.8 for further details • In particular, get used to Figure 3.18
Conclusion • Read Chapter 3 in conjunction with Appendix A • You will miss many details – go back and read it again and again after we have discussed the MIPS hardware architecture. • Now is the time to get familiar with assembly language programming! No cheating! • Make sure that you program at least two procedures this weekend. • Have a close look at the simulator. What does it do with pseudo-instructions?