So i have this code in C that i have to translate into assembly
int a[10]={0,1,2,3,4,5,6,7,8,9};
int i, j, k;
i = 1;
goto abc;
def:
j = 1;
k = 4;
goto ghi;
i = 2;
abc:
goto def;
ghi:
if (i==j){
a[2] = a[3];
}else{
a[2] = a[4];
}
while(k>0){
a[k] = 7;
k = k - 1;
}
if((i>k) && (i<10)){
if((k==6) || (j>=i)){
a[9] = 400;
}else{
a[9] = 500;
}
}
switch(j){
case 0: a[6] = 4; break;
case 1: a[6] = 5; break;
case 2: a[6] = 6; break;
case 3: a[6] = 7; break;
}
I have been able to turn only the goto parts into assembly because i don't know how to turn the if's else's and switch commands into MIPS assembly Here what i have done so far
.text
main:
li $t0, 1
lw $t0, variableI ## i = 1
j abc ## goto abc
def:
li $t0, 1
lw $t0, variableJ ## j=1
li $t0, 4
lw $t0, variableK ## k=4
j ghi ## goto ghi
li $t0, 2
lw $t0, variableI ## i = 2
abc:
j def ## goto def
ghi:
.data
variableI: .word
variableJ: .word
variableK: .word
vetorA: .word 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
It isn't necessary to translate all code for me just need a good explanation of how to use if's and else's since i haven't found any really good explanation online.
The instruction set manual is online that will cover all of it. As well as compilers.
unsigned int fun ( unsigned int a, unsigned int b, unsigned int c )
{
unsigned int r;
r = 0;
if(a==5)
{
r=6;
}
return(r);
}
mips-elf-gcc -O2 -c -fno-delayed-branch so.c -o so.o
mips-elf-objdump -d so.o
so.o: file format elf32-bigmips
Disassembly of section .text:
00000000 <fun>:
0: 24020005 li $2,5
4: 10820004 beq $4,$2,18 <fun+0x18>
8: 00000000 nop
c: 00001025 move $2,$0
10: 03e00008 jr $31
14: 00000000 nop
18: 24020006 li $2,6
1c: 03e00008 jr $31
20: 00000000 nop
equals and not equals are easy, bne, beq...
it is often common for the compiler to generate the opposite something like this in this case
return reg = 0;
compare input reg with 5
if NOT equal then branch to skip
return reg = 6
skip:
return
But not always, gcc did this
0: 24020005 li $2,5
4: 10820004 beq $4,$2,18 <fun+0x18>
8: 00000000 nop
r2 is the return register load it with a 5 as a temporary register for now in order to do the comparision. compare the input reg (r4) with 5 if equal then branch to address 18. If not equal keep going.
If not equal then
c: 00001025 move $2,$0
10: 03e00008 jr $31
14: 00000000 nop
put a 0 in the return register r2 and return. this path is the equivalent of
r = 0;
return(r);
If it is equal to 5 then
18: 24020006 li $2,6
1c: 03e00008 jr $31
20: 00000000 nop
put the 6 in r2 and return
For this example C code the compiler is very brute force about the solution, other than not incurring more branches to have a single exit point (not-atypical).
unsigned int fun ( unsigned int a, unsigned int b )
{
unsigned int r;
r = a;
switch(b)
{
case 5: r+=3; break;
case 7: r^=3; break;
}
return(r);
}
sometimes you will see the tools generate a jump table, depends on the architecture and other factors, in this case that is not going to happen but if you had switch(b&3) and then the four possible cases, I tried and gcc did not make a jump table.
But what is a switch really? in this case and in all cases it is no more than if (argument in the parens, in this case just b by itself) b is 5 else of b is 7 then. A switch is an if-then-else tree and often that is all a compiler will bother to implement.
00000000 <fun>:
0: 24030005 li $3,5
4: 00801025 move $2,$4
8: 10a30009 beq $5,$3,30 <fun+0x30>
c: 00000000 nop
10: 24030007 li $3,7
14: 14a30004 bne $5,$3,28 <fun+0x28>
18: 00000000 nop
1c: 38820003 xori $2,$4,0x3
20: 03e00008 jr $31
24: 00000000 nop
28: 03e00008 jr $31
2c: 00000000 nop
30: 24820003 addiu $2,$4,3
34: 03e00008 jr $31
38: 00000000 nop
r = a
4: 00801025 move $2,$4
if b == 5 then
0: 24030005 li $3,5
8: 10a30009 beq $5,$3,30 <fun+0x30>
c: 00000000 nop
r+=3 and return
30: 24820003 addiu $2,$4,3
34: 03e00008 jr $31
38: 00000000 nop
(else) if b==7
10: 24030007 li $3,7
14: 14a30004 bne $5,$3,28 <fun+0x28>
18: 00000000 nop
r ^=3 and return
1c: 38820003 xori $2,$4,0x3
20: 03e00008 jr $31
24: 00000000 nop
else return (r was set to a up front)
28: 03e00008 jr $31
2c: 00000000 nop
so it is a simple if-then-else tree with one non brute force out of order kind of thing the r = a was placed in the middle of the if b == 5 were mixed together.
unsigned int fun ( unsigned int a )
{
unsigned int r;
r = 0;
if(a<5)
{
r = 3;
}
return(r);
}
00000000 <fun>:
0: 2c840005 sltiu $4,$4,5
4: 14800004 bnez $4,18 <fun+0x18>
8: 00000000 nop
c: 00001025 move $2,$0
10: 03e00008 jr $31
14: 00000000 nop
18: 24020003 li $2,3
1c: 03e00008 jr $31
20: 00000000 nop
because of how mips works or at least the mips I have compiled for
set if less than unsigned
0: 2c840005 sltiu $4,$4,5
since the way the C was written we can actually discard the a variable with the if less than question. So if r4 (a) is less than 5 then "set" r4 (non-zero)
so now less than becomes an equal or not equal question
if(r4 is not equal to zero) combined with the above means if a is less than five then
4: 14800004 bnez $4,18 <fun+0x18>
8: 00000000 nop
return 3
18: 24020003 li $2,3
1c: 03e00008 jr $31
20: 00000000 nop
else return 0
c: 00001025 move $2,$0
10: 03e00008 jr $31
14: 00000000 nop
Mips doesn't like/use flags like most other instruction sets. Most others you would have a compare instruction which does a subtract and sets a bunch of flags but does not store the subtraction to a register, then subsequent instructions will use those flags. mips uses a philosophy of no flags so do the comparison and act on it in the same instruction. So for example another architecture:
00000000 <fun>:
0: e3500004 cmp r0, #4
4: 93a00003 movls r0, #3
8: 83a00000 movhi r0, #0
c: e12fff1e bx lr
compare a with 4 then if less than or same r = 3 if higher r = 0 and return. This is in a way also very atypical in that this instruction set shown here (arm) allows for per-instruction conditional execution rather than only branches are conditional and mov and add and such are not.
And this is more typical
00000000 <_fun>:
0: 0a00 clr r0
2: 2d97 0002 0004 cmp 2(sp), $4
8: 8301 blos c <_fun+0xc>
a: 0087 rts pc
c: 15c0 0003 mov $3, r0
10: 0087 rts pc
and this is almost brute force one to one
r = 0
0: 0a00 clr r0
compare a (passed in on the stack) with 4
2: 2d97 0002 0004 cmp 2(sp), $4
branch if lower or same to address c:
8: 8301 blos c <_fun+0xc>
if 5 or higher then return (with r = 0)
a: 0087 rts pc
if less than 5 (less than or equal to 4) then return 3
c: 15c0 0003 mov $3, r0
10: 0087 rts pc
(destination is on the right here mov $3,r0 means r0 = 3. $ means constant here)