210 likes | 322 Views
CS 161 Lecture 4. Prof. L.N. Bhuyan http://www.cs.ucr.edu/~bhuyan/cs161/index.html. While in C/Assembly: Summary. C. while (save[i]==k) i = i + j; ( i , j , k : $s3,$s4,$s5: base of save[] :$s6)
E N D
CS 161Lecture 4 Prof. L.N. Bhuyan http://www.cs.ucr.edu/~bhuyan/cs161/index.html
While in C/Assembly: Summary C while (save[i]==k) i = i + j; (i,j,k: $s3,$s4,$s5: base of save[]:$s6) Loop: add $t1,$s3,$s3 #$t1 = 2*i add $t1,$t1,$t1 #$t1 = 4*i add $t1,$t1,$s6 #$t1=Addr lw $t1,0($t1) #$t1=save[i] bne $t1,$s5,Exit#goto Exit#if save[i]!=kadd $s3,$s3,$s4 # i = i + j j Loop # goto Loop Exit: MIPS
If less in C/Assembly C if (g < h) go to Less slt $t0,$s0,$s1 # $t0 = 1 if# $s0<$s1 (g<h) bne $t0,$zero, Less # goto Less# if $t0!=0. . .# (if (g<h)) Less:A branch if $t0 != 0 branches if g < h. • Register $zero always 0, so use bne comparing register $t0 to register $zero • How test if (g >= h)? MIPS
C case/switch statement • Choose among four alternatives depending on whether k has the value 0, 1, 2, or 3 switch (k) { case 0: f=i+j; break; /* k=0*/ case 1: f=g+h; break; /* k=1*/ case 2: f=g–h; break; /* k=2*/ case 3: f=i–j; break; /* k=3*/ }
Case/Switch via Jump Address Table • Notice that last case must wait for n-1 tests before executing, making it slow • Alternative tries to go to all cases equally fast: jump address table for scale-ability • Idea: encode alternatives as a table of addresses of the cases • Table is an array of words with addresses corresponding to case labels • Program indexes into table and jumps • MIPS instruction “jump register” (jr) unconditionally branches to address in register; use load to get address
Jump Address Table: Summary slti $t3,$s5,0 #Test if k < 0 bne $t3,$zero,Exit #if k<0,goto Exit slti $t3,$s5,4 # Test if k < 4 beq $t3,$zero,Exit #if k>=4,goto Exit add $t1,$s5,$s5 # Temp reg $t1 = 2*k add $t1,$t1,$t1 # Temp reg $t1 = 4*k add $t1,$t1,$t2 #$t1=addr JumpTable[k] lw $t1,0($t1) # $t1 = JumpTable[k] jr $t1 # jump based on $t1L0: add $s0,$s3,$s4 # k=0 so f = i + j j Exit # end case, goto ExitL1: add $s0,$s1,$s2 # k=1 so f = g + h j Exit # end case, goto ExitL2: sub $s0,$s1,$s2 # k=2 so f = g – h j Exit # end case, goto ExitL3: sub $s0,$s3,$s4 # k=3 so f = i – jExit: # end of switch statement
MIPS Instruction Set Revealed So Far • MIPS Instructions: • arithmetic: add, sub, addi, slt, slti • data transfer: lw, sw • conditional branch: beq, bne • unconditional branch: j, jr • Machine Language Formats: • R-Register • I-Immediate • J- Jump
2.7 Functions and procedures • Place parameters in argument registers – where the procedure can access them • Transfer control to the procedure • Acquire storage needed for procedure • Perform desired task • Place the result in value registers – where the calling program can access them • Return control to the main program by using jra instruction
Registers used: $a0, $a1, $a2, $a3 $ra $v0, $v1 $s0, $s1, …, $s7; Must consider: Parameters (arguments) Return address Return value Local variables Function Call Bookkeeping Jr $ra – Jump to the address contained in the return register ra.
Passing Parameters and Return C ... sum(a,b);... /* a,b:$s0,$s1 */}int sum(int x, int y) { return x+y;} Caller ProgramPass up to four parameters in the argument registers: $a0, $a1, $a2, $a3, and jump to procedure Sum. 1000 add $a0,$s0,$zero # x = a1004 add $a1,$s1,$zero # y = b1008 addi $ra,$zero,1016 #$ra=10161012 j sum #jump to sum1016 ... <- Return address 2000 sum: ... 20xxjr $ra MIPS
Instruction Support for Functions • Want single instruction to jump and save return address: jump and link (jal): • Before:1008 addi $ra,$zero,1016 #$ra=10161012 j sum #go to sum1016 ... • After:1008jal sum# $ra=1012,go to sum1012...
Saving the Register Contents • The procedure may use the same registers that were used by the main (caller) and will be later needed by the main,so these must be saved in the stack by the procedure before using them • After the procedure completes, load these values from the stack back to the registers. Then return to the main by using jr. • To limit the register spilling, MIPS uses the following convention. 1. $t0-$t9: 10 temporary registers, not preserved by the procedure (callee) 2. $s0-s7: 8 saved registers that must be preserved if used by the procedure.
Exceeding limits of registers • Recall: assembly language has fixed number of operands, HLL doesn’t • Local variables: $s0, ..., $s7,$t0, …, $t9 • What if more than 18 words of local variables? • Arguments; $a0, ..., $a3 • What if more than 4 words of arguments? • More argument registers needed for nested loops • More return addresses (Ra) needed for nested loops • Place extra local variables and extra arguments onto stack
Convert to a Procedure • Compile by hand using registers:f = (g + h) - (i + j); Register Allocations:f: $s0, g: $s1, h: $s2, i: $s3, j: $s4 • MIPS Instructions: add $s0,$s1,$s2 # $s0 = g+h add $t1,$s3,$s4 # $t1 = i+j sub $s0,$s0,$t1 # f=(g+h)-(i+j) If it’s a procedure, g,h,i,j will be passed through $a0,$a1,$a2,$a3. Registers $s0,and $t1 need to be saved in the stack. addi $sp,$sp, -8 # Adjust stack for 2 items sw $t1, 4($sp) # save register $t1 sw $s0, 0($sp) add $s0,$a0,$a1 # $s0 = g+h add $t1,$a2,$a3 # $t1 = i+j sub $s0,$s0,$t1 # f=(g+h)-(i+j) add $v0,$s0,$zero # Return value of f Body
Restore Registers Before returning, restore the old values in the registers lw $s0, 0($sp) lw $t1, 4($sp) addi $sp, $sp, 8 # adjust stack pointer jr $ra # Jump back to main
MIPS: Software conventions for Registers 0 zero constant 0 1 at reserved for assembler 2 v0 expression evaluation & 3 v1 function results 4 a0arguments 5 a1 6 a2 7 a3 8 t0temporary: caller saves . . . (callee can clobber) 15 t7 16 s0callee saves . . . (caller can clobber) 23 s7 24 t8temporary (cont’d) 25 t9 26 k0 reserved for OS kernel 27 k1 28 gp Pointer to global area 29 sp Stack pointer 30 fp frame pointer 31 ra Return Address (HW) Plus a 3-deep stack of mode bits.
Nested Procedures Call Procedure within procedure. How to pass arguments? How to store return address? The conflicts are solved by pushing all these registers into the stack.
Stack $sp $sp Stack $sp The Stack Before procedure call During procedure call stack grows down Stack $FP 1 1 Saved argument registers (if any, addressed by FP) 2. Saved return address 3. Saved saved registers (if any from nested loops) 4 Local arrays and structures 2 3 4 After procedure Call $sp always points to “top” stack element and $FP (Frame Pointer) points to the first word of procedure frame
2.8 Instruction Support for Characters • MIPS (and most other instruction sets) include 2 instructions to move bytes: • Load byte (lb) loads a byte from memory, placing it in rightmost 8 bits of a register • Store byte (sb) takes a byte from rightmost 8 bits of register and writes it to memory • Declare byte variables in C as “char” • Assume x, y are declared char, y in memory at 0($gp) and x at 1($gp). What is MIPS code for x = y; ? lb $t0,0($gp) # Read byte ysb $t0,1($gp) # Write byte x
001111 00000 10000 0000 0000 0000 1111 0000 0000 0000 1111 0000 0000 0000 0000 2.9 What if constant bigger than 16 bits? • Must keep instructions same size, but immediate field (addi) only 16 bits • Add instruction to load upper 16 bits, then later instruction gives lower 16 bits • load upper immediate (lui) sets the upper 16 bits of a constant in a register • Machine language version of lui $s0,15 • Contents of $s0 after executing lui $s0,15 op rt rs
001111 001000 00000 10001 10001 10001 0000 0000 0000 0001 0011 1000 1000 0000 Big Constant Example • C: i = 80000; /* i:$s1 */ • MIPS Asm: • 80000ten = 0000 0000 0000 0001 0011 1000 1000 0000two • lui $s1, 1 addi $s1,$s1,14464# 0011 1000 1000 0000 • MIPS Machine Language $s1: 0000 0000 0000 0001 0011 1000 1000 0000