how can i convert this MIPS code to C code?

Viewed 31

This is MIPS code i wrote. How can i convert this MIPS code to C code? For me, label, for-loop, memory address, negative int are difficult concept to translate. Since i haven't learned C, it will be very thankful to show me examples.

.data 0x10010000

a:
.word 30
.word 50
.word -10
.word 45
.word 100

.text
.globl main

main:
lui $s0, 0x1001
addi $s1, $0, 5
add $t0, $0, $0
add $s2, $0, $0

for:
slt $t1, $t0, $s1
beq $t1, $0, end
lw $t2, 0($s0)
add $s2, $s2, $t2
addi $t0, $t0, 1
addi $s0, $s0, 4
j for

end:
nop
jr $ra
1 Answers

Assembly language uses if-goto-label, whereas high level languages use structured statements.  So, look for the patterns of how structured statements are turned into if-goto-label.


Generally speaking, loops like for, while, do..while will have backward branches, whereas if-then, if-then-else will have forward branches.


A while loop will have:

  1. a loop label,
  2. a condition test (exit test),
  3. a loop body, and,
  4. an unconditional backwards branch to the label to repeat the loop
  5. an exit label (used by 2.)

A for loop is similar but adds some things:

  1. an initializer (added by for)
  2. a loop label,
  3. a condition test (exit test),
  4. a loop body,
  5. an increment (added by for)
  6. an unconditional backwards branch to the label to repeat the loop
  7. an exit label (used by 3.)

An if-then will have:

  1. a condition test that branches around the then-part to the end of the if
  2. a then-part
  3. a label for the end of the if statement (used in step 1.)

An if-then-else will have:

  1. a condition test that branches around the then-part and goes to the else-part
  2. a then-part
  3. an unconditional branch that goes to the end of the if (skipping the else-part)
  4. a label for the else-part
  5. the else-part
  6. a label for the end of the if statement (used in step 1.)

There are also do while loops where the condition (exit) test is at the end, so these are found in substitution of the unconditional backwards branch on the other loops.

There is also a more general loop type where the condition test to exit the loop is in the middle — these I would do as infinite loop [e.g. while(1) {...}] with some if (...) break; located within the body as needed.

Of course, in assembly, these patterns do not have to be followed exactly, so, may take some work to identify the patterns.  Find a matching pattern and you can convert the control structure to the equivalent structured statement, then what's left is to convert the expressions and body (or then/else part) statements.


The lui $s0, 0x1001 is taking the address of a, but using hard-coded constant.  We don't have to do this in assembly: could have done la $s0, a instead, and we wouldn't use that hard-coded constant in C unless we were dealing with some kind of embedded system.  Instead in C we would take the address of the array, quite simply as in int *p = a; which creates a pointer to be used wherever $s0 is used when the intent is to refer to the array a.


The increment of $s0 by 4, says to increment the pointer by 4 bytes, and the effect is to move the pointer to refer to the next successive element in the array.  This is done in C as p++; — an increment of 1 in C means 1 × size of a single element of the array, and as the array elements are int, they are 4 bytes in size.  Since the scaling is automatic in C based on the (pointer) variable type, increment of 1 of an int pointer in C is equivalent to increment of 4 in assembly.


Your data declaration for a can be done using an int array as in int a [] = { 100, -100 }; which creates an array of 2 ints, one element initialized to a positive value and one to a negative value.


You don't have registers in C so instead you create named variables, like p above.  This is done for all your longer lived variables (here $s0, $s1, $s2, $t0).  Many short lived register usages can convert into some expression in C and thus won't require variable declarations (though those won't hurt your C code if you choose to create short lived variables).


These conversions work bidirectionally (from assembly to C and from C to assembly), but be advised to translate as literally as possible rather than making adjustments or optimizations during translation.

Related