Вы находитесь на странице: 1из 6

Spring 2007 CS61c Week 4 Discussion Notes

Michael Le (cs61c-ta@imail.eecs.berkeley.edu)

Going from C to MIPS


MIPS, or any other assembly language for that matter, is human readable form of the language the processor understands. Although assembly language has commonalities with high level languages you have seen such as Scheme, Java, and C, assembly language cannot be placed in the same realm as those languages because of the level detail the language deals with. In high level languages, a lot of the hardware is hidden from the programmer, but with assembly language, the hardware is exposed. As a result, programmers not only have to keep track of what they are doing, but also keep track of where their data is located and how it is interpreted.

Working with MIPS One significant difference between assembly language (i.e. MIPS) and high level languages like C is where work is done. In C, work is done with statements and variables keep track of the data. The equivalent things in assembly are instructions and registers. Unlike high level languages, assembly languages have a limited amount of registers and thus force the programmer to keep track of what each register contains and how it should be interpreted. This brings up the second significant difference between high level languages and assembly language: registers do not carry type as it is the instructions themselves that will give the register its type. That means that a single register can be interpreted as a signed integer at one point in the language, a character at another point, and a pointer in a third. The lack of types often causes students confusion because students are used to the fact that a variable holds one type of thing. Therefore, when a student accepts that registers can be of any type and that instructions dictate how a register will be interpreted irrelevant of how that register has been used in the past, the student is well on his/her way to understanding assembly language

The Power of MIPS All the instructions that are available in MIPS can be found on the green card of your COD book. If you do not have that, try to copy that sheet from your friend as it is a handy guide to the instructions (and a lot more) for the midterm/finals ;-). In the meantime, the last section of Appendix A has a list of all the instructions SPIM will understand and also provides brief descriptions of what each instruction will do. So, if you are in doubt of what an instruction does or what is available, Appendix A is where you want to go. As heads up for the midterm and final, all the instructions that are useful to you are on the green sheet and the use of some of the instructions in the Appendix A (i.e. the pseudoinstructions) are not recommended. Many MIPS related questions in the midterm/final will deal with most of the instructions on the green sheet so familiarizing yourself with those instructions is in your best interest.

The Meaning of Overflow Like many other things in CS, some things are poorly named or have different meanings in different contexts. In MIPS, the letter u is abused. Depending on the kind of instruction, it can take on one of

three different meanings. 1. arithmetic instructions a letter u with an arithmetic instruction means ignore overflow. This means if the true value was not achieved after the execution of the instruction, do not notify the program. 2. comparison instructions a letter u with a comparison instruction means compare the two values via unsigned. As you know, 0x80000000 and 0x00000000 generate two different results when compared signed and unsigned. 3. memory instructions -- a letter u with a memory instruction means do not sign-extend the most significant bit when retrieving values from memory. In MIPS, it is possible to read in only 1 or 2 bytes with a memory instruction. Since MIPS registers (in this class) are 32-bits, we have a choice of how to fill in the upper 24 and 16 bits respectively.

Mapping Between C and MIPS The following may be useful conversion patterns of C code and MIPS. Note it is not a comprehensive list of all patterns of C code you have seen but it should give you an idea of how things work. Arithmetic
i = j + k; i = j k; i = j + k + 4; add sub addi add sll sll $t0, $t1, $t2 $t0, $t1, $t2 $t0, $t2, 4 $t0, $t0, $t1 $t0, $t0, 2 $t0, $t0, 2 # i = j + k # i = j - k # i = k + 4 # i = i + j # i = i << 2 # i = i << 2

i = i << 2; i = i * 4;

If equals
if( a == b ) { // work #1 } else { // work #2 } bne $t0, $t1, else # work 1 j fin else: # work 2 fin: # a == b

If not equals
if( a != b ) { // work #1 } else { // work #2 } beq $t0, $t1, else # work 1 j fin else: # work 2 fin: # a != b

If less than/greater than


if( a < b ) { // work #1 } else { // work #2 } slt $t2, $t0, $t1 beq $t2, $zero, else # work 1 j fin else: # work 2 fin: # a < b # if a >= b, branch

If less than equals/greater than equal


if( a <= b ) { // work #1 true: } else { // work #2 } else: # work 2 fin: beq $t0, $t1, true slt $t2, $t1, $t0 bne $t2, $zero, else # work 1 j fin # b < a # if b >= a, branch

Arrays (a.k.a pointers)


A[2] lw $t0, offset($s0) # A = $s0 # replace offset with 2 * sizeof(type of A) # if type of A is int, then offset is 8 # and the instruction is # # lw $t0, 8($s0) multi $t1, $t0, sizeof # i * sizeof # replace sizeof with sizeof type of A # if type of A is int, then size is 4 # and the instruction is # # multi $t0, $t1, 4 add $t1, $s0, $t1 # A + (i * sizeof) lw $t1, 0($t1) # *(A + i * sizeof) addi $t2, $0, 4 # load 4 temporarily multi $t1, $t0, sizeof # i * sizeof # replace sizeof with sizeof type of A # if type of A is int, then size is 4 # and the instruction is # # multi $t0, $t1, 4 add $t1, $s0, $t1 # A + (i * sizeof) sw $t2, 0($t1) # *(A + i * sizeof)

A[i]

A[i] = 4;

A few other constructs that I have not covered are switches, multi-dimensional arrays, and struct field referencing (. and ->). Each of these three constructs is built off of the ones you see above. So, a good exercise is to try to do a conversion yourself. In next discussion, we will go over an example of the MIPS behind switches, multi-dimensional arrays, and struct field referencing.

Example of C to MIPS translation Given the following C code:


for(i = 0; i < foo; i++) { array[i] = array[i+1] + 9; sum += array[i+2]; } // Expansion of [] notation // *(A + (i << 2))=*(A + ((i + 1) << 2)) + 9 // sum = *(A + ((i + 2) << 2))

The equivalent MIPS instructions to do the same job are as follows:


add slt beq addi sll add lw addi sll add sw addi sll add lw add addi j fin: $s1, $0, $0 $t0, $s1, $s2 $t0, $zero, end $t0, $t0, $t0, $t0, $t0, $t1, $t1, $t0, $t0, $t0, $t0, $t0, $v0, $s1, 1 $t0, 2 $s0, $t0 0($t0) $t0, 9 $s1, 2 $s0, $t1 0($t1) $s1, 2 $t0, 2 $s0, $t0 0($t0) $v0, $t0 # i = 0 # if !(i < foo) # goto fin # # # # # # # # # # # # # i + 1 (i + 1) << 2 -- mult by 4 to match sizeof(int) A + ((i + 1) << 2) *(A + ((i + 1) << 2)) *(A + ((i + 1) << 2)) + 9 i << 2 -- mult by 4 to match sizeof(int) A + (i << 2) *(A + (i << 2)) = *(A + ((i + 1) << 2)) + 9 i + 2 (i + 1) << 2 -- mult by 4 to match sizeof(int) A + ((i + 2) << 2) *(A + ((i + 2) << 2)) sum = *(A + ((i + 2) << 2))

loop:

$s1, $s1, 1 loop

# i++

Note: A lot of these instructions are redundant and thus, this assembly code could be optimized. However, a blind conversion of C code will produce a result similar to this. Also, there is more than one way to do the same code. As an exercise, how could you do some things differently?

Spring 2007 CS61c Week 4 Discussion Notes


Michael Le (cs61c-ta@imail.eecs.berkeley.edu)

Going from C to MIPS Worksheet


Problem 1: Memory Management Review a) What are the four regions of memory we have discussed in class? How are each of these regions used (i.e. what is their purpose)?

b) Explain the three different schemes of traversing the heaps free list?

c) Explain two alternative ways to manage the heap.

d) What is the difference between external and internal fragmentation?

e) Explain the three ways to do garbage collection.

Problem 2: Translating C to MIPS #1 Translate the following C code at right into MIPS. Assume a is in $s0 and b is in $s1.
beq $s0, $0, end addi $t0, $0, 5 bne $s1, $t0, end #insert code here end:

if (a != 0 && b == 5) { /*insert code here*/ }

Problem 3: Translating C to MIPS #2 Translate the following C code below into MIPS. Assume i is in $s0, arr1 is in $s1, aar2 is in $s2, and len in $s3.
addi int int int int *arr1; *arr2; len; i; loop: # assume that len >= 0 for # this to work beq $s0, $s3, done # t1 = 4*i (we must do this # because ints are 4 bytes) add $t1, $t0, $t0 add $t1, $t1, $t1 add lw add sw addi j done: $t2, $t3, $t2, $t3, $s0, loop $s2, $t1 0($t2) $s1, $t1 $($t2) $s0, 1 $s0, $0, 0 #i = 0

/* some other code here which initializes the two arrays (i.e. presumably arr1 and arr2 aren't garbage) */ for (i = 0; i < len; i++) { arr1[i] = arr2[i]; }

#t3 = arr2[i] #arr1[i] = t3 #i++

Problem 4: Reverse Engineering MIPS In a sentence or two, explain what the following MIPS code does. Also, what kind of value must be in $t0 to allow the code to run?
# ptr loaded into $t0 andi $t1, $t0, 0x3 foo: bne $t1, $zero, end addi $t1, $t0, 12 loop: lw $t2, 0($t0) lw $t3, 0($t1) addi $t0, $t0, 4 addi $t1, $t1, -4 sw $t2, 4($t1) sw $t3, -4($t0) slt $t3, $t0, $t1 bne $t3, $zero, loop end:

This code swaps the endianess of a 64-bit integer. This code will only do the swap if the pointer is word aligned.

Вам также может понравиться