Lecture 3 - MIPS, Procedures

Thursday, June 19, 2014

2:29 PM

Example 3:

Compute an absolute value of \$1, store in \$1 and return

branches + jumps: modify PC (eg jr)

beq: branch is two registers have equal contents

• increment PC by a given # of words
• can branch backwards

bne: branch if not equal

slt: set less than

• slt \$a \$b \$c
• \$a gets 1 if \$b < \$c
• \$a gets 0 if otherwise

 Address Instruction 0000 0000 0000 0004 0000 0008 0000 000c slt \$2, \$1, \$0    ;(compare \$1 < 0) beq \$2, \$0, 1     ;if false, skipover sub \$1, \$0, \$1    ;negates \$1 jr \$31

Example: Looping

sum the integers 1..13, store in \$3, return

 Address Instruction 0000 0000 0000 0004 0000 0008 0000 000c 0000 0010 0000 0014 0000 0018 0000 001c lis \$2            ;\$2 <- 13 .word 13 add \$3, \$0, \$0    ;\$3 <- 0 add \$2, \$3, \$2    ;\$3 += \$2 lis \$1            ;\$1 <- 1 .word 1 sub \$2, \$2, \$1 bne \$0, \$0, -5

RAM

• from RAM into registers
• lw \$a, i(\$b)
• load the word at MEM[\$b + i] into \$a

sw – “store word”

• from registers into RAM
• sw \$a, i(\$b)
• store the word \$a at MEM[\$b + i]

multiply

• mult \$a, \$b
• product of 2 32-bit numbers is 64 bits; too big for a register
• So two special registers, hi + lo, store the result of mult (and div)
• mult \$a, \$b = hi:lo <- \$a * \$b
• (for division, lo stores quotient, hi stores remainder)

mflo – move from lo

• mflo \$a = \$a <- lo

mfhi – move from hi

Example 5

\$1 = address of an array

\$2 = length of the array

Place element 5 (6th starting from 0) into \$3

 lw \$3, 20(\$1)     ;5x4, array slots are 4 bytes jr \$31

If the index is not known:

 lis \$5             ;\$5 = index I want .word ______ lis \$4 .word 4 mult \$5, \$4 mflo \$5            ;\$5 *= 5 add \$5, \$1, \$5     ;\$5 += \$1 lw \$3, 0(\$5)       ;\$3 <- MEM[\$5] jr \$31

Revisiting loop example:

Improvement: you can take out the lis and .word 1 out of the loop to make the loop run faster.

• have to make sure the branch index is still consistent
• when explicit branching exists
• adding/removing instructions => change branch offsets
• Instead, the assembler allows labeled instructions:

 label: instruction foo: add \$1, \$2, \$3

The assembler associates the name foo with the address of add \$1, \$2, \$3 in the binary.

 lis \$2    .word 13    add \$3, \$0, \$0 top:        ;top = 0x0c    add \$3, \$3, \$2    lis \$1    .word 1    sub \$2, \$2, \$1    bne \$2, \$0, top    jr \$31    ;20

assembler computes the difference between PC and top, in words

• ie (top – PC)/4 = (0C – 20)/4 = -5

Procedures

Two problems to be solved

• call and return
• how to transfer control into and out of the procedure
• parameters?
• registers
• what if a procedure f overwrites the main line’s data?
• we could reserve some registers for f and some for the mainline – with no overlap
• what if f calls g?
• what if f calls f?
• Instead, guarantee that procedure leave registers unchanged when done.
• How? Use RAM
• Which RAM? How do we keep procedures from using the same RAM?
• solution: allocate memory from the top or bottom of free RAM. Need to keep track of which RAM is used and which RAM isn’t.
• Machine helps us out. \$30 initialized (by the loader) to just past the last word of memory. We can use \$30 as a “bookmark” to separate used & unused RAM if we allocate from the bottom.

Example

f calls g

g calls h

h returns

g returns

h returns

RAM:

 Code h save g save f save

\$30 gets changed accordingly (like a stack)

• strategy: each procedure pushes the registers it will use onto the stack, and pops the original values from the stack when done.
• \$30 – the stack pointer – contains the address of the top of the stack

Template for writing procedures

 f: sw \$2, -4(\$30)    sw \$3, -8(\$30)     ; push registers f will modify onto stack    lis \$3    .word 8    sub \$30, \$30, \$3   ; decrement stack ptr       add \$30, \$30, \$3   ; increment stack ptr    lw \$3, -8(\$30)    lw \$2, -8(\$30)

.

Created with Microsoft OneNote 2010
One place for all your notes and information