Jump to content


Check out our Community Blogs

Register and join over 40,000 other developers!


Recent Status Updates

View All Updates

Photo
- - - - -

converting c code to mips

mips c

This topic has been archived. This means that you cannot reply to this topic.
9 replies to this topic

#1 CrossMan

CrossMan

    CC Lurker

  • New Member
  • Pip
  • 5 posts

Posted 09 June 2014 - 09:23 AM

Hello everyone, it would be very kind of yours if you could tell me if the following conventions i made are correct or not so i can understand mips better . 
1) c code
for (i=0;i<10;i++)
           a+=b;

mips with a,b,i on $s0,$s1,$t0
add $t0 ,$zero , $zero
      Loop:  slti $t1,$t0,10
             beq $t1,$zero,Exit
             add $s0,$s0,$s1
             addi $t0,$t0,1
             J Loop
       Exit:
 
2)c code
 
while (save[i] = = k) 
 i + = 1;
 
Mips with i,k on $s3,$s5 and the base of save[]  on $s6
 
Loop: sll $to,$s3 , 2
            add $t1,$s6,$t0
            lw $t2 , 0 ($t1)
            bne $t2 , $s5 , Exit
            addi $s6,$s6,1
            J Loop
       Exit:

Thanks in advance for your help / suggestions / corrections :)/>/>
By the way, can anyone make clear to me the difference between a saved and a temporary register ? 
thanks again :)/>/>


#2 dargueta

dargueta

    I chown trolls.

  • Moderator
  • 4854 posts

Posted 09 June 2014 - 01:06 PM

For #2:

 

1) There is no space between the = in ==, nor a space between the + and = in +=.

2)  sll $t0, $s3, 2

3) You're correct but it could be more efficiently written:

    sll     $t0, $s3, 2
    add     $t0, $t0, $s6
loop:
    lw      $t1, ($t0)
    bne     $t1, $s5, exit
    addi    $t0, $t0, 4
    j       loop

First you establish $t0 as a pointer into save by multiplying i by four and adding it to the base address of save. This is exactly what you've done.

 

However, you don't need to increment i at all! Instead of adding 1 and multiplying by 4, you can just add 4 each time.

 

As for saved vs. temporary registers:

 

saved register ($s0-$s8) are registers that you're free to use but before you use them you have to save their values somewhere (usually the stack) and restore them once you're done. Whenever you call a function, you can be certain that the values in any of the s registers will be the same as before you called that function.

 

Temporary registers ($t0-$t9) are registers that you're free to use and don't have to save before using. When you call a function, never expect any of the t register to have the same value as they did before you called that function.

 

An example:

# Save $s0 and $ra on the stack
subi    $sp, $sp, 8
sw      $s0, ($sp)
sw      $ra, 4($sp)

# Set $s0 and $t0 to 0
add     $s0, $s0, $0
add     $t0, $t0, $0
jal     some_function

# $s0 = 0, $t0 = <some unknown value, maybe 0 by coincidence>

# Restore $s0 on the stack
lw      $ra, 4($sp)
lw      $s0, ($sp)
addi    $sp, $sp, 8

# Return
jr      $ra

Edited by dargueta, 09 June 2014 - 01:18 PM.
Forgot to return from the function. -__-

sudo rm -rf / && echo $'Sanitize your inputs!'


#3 CrossMan

CrossMan

    CC Lurker

  • New Member
  • Pip
  • 5 posts

Posted 09 June 2014 - 01:45 PM

I am very grateful for your help mister dargueta, thanks for pointing out for me that shortcut on (3) :)

as about the saved and temp let me ask some more things to make sure i got it 

sw $s0, ($sp)
add $s0,$zero,$zero 
.
.
.
other stuff
.
.
.
addi $s0 , $zero, 15

jal func      //in the function it will be called it will have the value 15 if i do 
              //lw $s0,($sp) ?


 

and some other kind of questions about the temporaries 

addi $sp,$sp,-4
addi $t0,$zero,5
sw   $t0,($sp)
jal somewhere // if i lw it in that function it will still be 5 right ?



// If i do the following 
addi $sp,$sp,-4
sw   $t0,($sp)
addi $t0,$zero,5
jal somewhere // will it work the same as before ? and if yes whats the point of having 
              //saved and temp ?

Once again thanks in advance for you assist :)



#4 dargueta

dargueta

    I chown trolls.

  • Moderator
  • 4854 posts

Posted 11 June 2014 - 11:23 AM

First and second questions:

 

Yes, you're correct, but:

1) You also have to save $ra before a function call.

2) A function should never access another function's local variables via the stack.

 

Third question:

You can save any registers you want on the stack. The distinction between saved and temporary registers is that

 

1) You must save saved registers onto the stack before using them at the beginning of your function and restore them just before you return from your function. As such, whenever you call a function, you can assume that none of the s registers will change.

 

2) You don't have to save temporary registers onto the stack before using them. Whenever you call a function, you cannot assume that any of the t registers will have the same value as they did before that function got called.


sudo rm -rf / && echo $'Sanitize your inputs!'


#5 CrossMan

CrossMan

    CC Lurker

  • New Member
  • Pip
  • 5 posts

Posted 20 June 2014 - 09:01 AM

Well i have another example i tried here, can you please help me see if it is correct or not and if not how ?

 

c code

int f(int a, int b, int n){
      if (n==0)
          return b;
      else 
          return f (a+b,a,n-1)
}

and mips here

f:addi sp,sp,-16
  sw   ra,a0,a1,a2 // forgive my laziness to write these command properly and to use $
  bne a2,zero,L1
  lw a2,a1,a0,ra
  add v0,zero,a1
  jr ra

L1:
    add t0,0,a0
    add a0,a0,a1
    add a1,t0,0
    addi a2,a2,-1
    jal fib


#6 dargueta

dargueta

    I chown trolls.

  • Moderator
  • 4854 posts

Posted 20 June 2014 - 01:11 PM

1) You save your arguments and return address on the stack but never restore them. Without restoring $ra the function will keep calling itself over and over again until your stack runs out of space and your program crashes.

2) You don't need to save the arguments.

f:
    subi    $sp, $sp, 4     # Allocate space for the return address
    sw      $ra, ($sp)      # Save the return address
    
    move    $v0, $a1        # Return value = b
    beqz    $a2, done       # Bail out if n == 0
    
    add     $t0, $a0, $a1   # $t0 = a + b
    move    $a1, $a0        # set a as second argument
    move    $a0, $t0        # set first argument to $t0 (a + b)
    subi    $a2, $a2, 1     # decrement third argument (n -= 1)
    jal     f
    
done:
    lw      $ra, ($sp)      # Restore the return address
    addi    $sp, $sp, 4     # Clean up the stack
    jr      $ra             # Return

Edited by dargueta, 20 June 2014 - 01:12 PM.

sudo rm -rf / && echo $'Sanitize your inputs!'


#7 CrossMan

CrossMan

    CC Lurker

  • New Member
  • Pip
  • 5 posts

Posted 21 June 2014 - 02:48 AM

Thanks a lot once again, i hope i am not bugging you a lot but a have a few more questions 

first another code translation attempt 

 

c code

f = g- A[B[4]];

mips

//f->so  g->s1 A base=s6 and B base - s7
lw t0, 16(s7)
sll t0, t0, 2
add t0, t0, s6
lw s0, 0(t0)
sub s0, s1, s0

Then i have something else troubling me . In my coursebook there are some translated programs but i dont understand why they do what follows

code 1

compare:
addi $sp, $sp, –4
sw $ra, 0($sp)
add $s0, $a0, $0    // whats the point of doing that
add $s1, $a1, $0    //and that ?
jal sub
addi $t1, $0, 1
beq $v0, $0, exit
slt $t2, $0, $v0
bne $t2, $0, exit
addi $t1, $0, $0
exit:
add $v0, $t1, $0
lw $ra, 0($sp)
addi $sp, $sp, 4
jr $ra
sub:
sub $v0, $a0, $a1
jr $ra

code 2 (another interpretation of the c code i tried on my last post)

fi:
addi $sp, $sp, –16
sw $ra, 12($sp)       
sw $s0, 8($sp)            // why he does all that instead of storing a0,a1,a2 ?
sw $s1, 4($sp)            //
sw $s2, 0($sp)            //
add $s0, $a0, $0          //
add $s1, $a1, $0          // 
add $s2, $a2, $0          //
add $v0, $s1, $0,         
bne $s2, $0, exit
add $a0, $s0, $s1
add $a1, $s0, $0
add $a2, $s2, –1
jal fi
exit:
lw $s2, 0($sp)
lw $s1, 4($sp)
lw $s0, 8($sp)
lw $ra, 12($sp)
addi $sp, $sp, 16
jr $ra

Thanks in advance, your help is very appreciated  



#8 dargueta

dargueta

    I chown trolls.

  • Moderator
  • 4854 posts

Posted 21 June 2014 - 01:07 PM

1) Your C to MIPS translation is correct.

2) add $s0, $a0, $0 is $s0 = $a0 + 0 so the end result is $s0 = $a0. Instead of doing add $s0, $a0, $0 SPIM will allow you to write move $s0, $a0 as more readable shorthand.

3) This way the programmer can keep the old values of $a0, $a1, and $a2 and reuse them for the arguments of the function being called. Because the s registers are saved registers they're guaranteed to be unmodified when the function you just called returns.


sudo rm -rf / && echo $'Sanitize your inputs!'


#9 CrossMan

CrossMan

    CC Lurker

  • New Member
  • Pip
  • 5 posts

Posted 21 June 2014 - 10:29 PM

2) I think i understand that but i dont see the point of doing it, cant he just use a0,a1  without moving them to s0, s1 ?

2)So it would work as well if he just stored a0,1,2 but putting them to s0,1,2 makes the code more 

comprehensible ?



#10 dargueta

dargueta

    I chown trolls.

  • Moderator
  • 4854 posts

Posted 23 June 2014 - 08:56 AM

To answer both questions simultaneously: You need temporary variables for the calculations and you must put the arguments in $a0-$a2. The calculations for the arguments depend on one another, so for example if the value for $a0 relies on the original values of $a1 and $a2, and the calculation for $a1 depends on the original value of $a0 and $a2, you already modified $a0 before you calculate $a1 so the result will be wrong.


sudo rm -rf / && echo $'Sanitize your inputs!'





Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download