如何解决MIPS 汇编如何使用 if 和 else 从 C 到 MIPS 汇编的翻译
所以我在 C 中有这段代码,我必须将其翻译成汇编
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;
}
我只能将 goto 部件转换为装配体,因为我不知道如何将 if 的 else 和 switch 命令转换为 MIPS 装配体 这是我到目前为止所做的
.text
main:
li $t0,1
lw $t0,variableI ## i = 1
j abc ## goto abc
def:
li $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,9
没有必要为我翻译所有代码,只需要很好地解释如何使用 if 和 else ,因为我还没有在网上找到任何很好的解释。
解决方法
在线说明集手册将涵盖所有内容。以及编译器。
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
等于和不等于很容易,bne,beq...
在这种情况下,编译器通常会生成相反的东西
return reg = 0;
compare input reg with 5
if NOT equal then branch to skip
return reg = 6
skip:
return
但并非总是如此,gcc 会这样做
0: 24020005 li $2,18 <fun+0x18>
8: 00000000 nop
r2 是返回寄存器,现在加载一个 5 作为临时寄存器以进行比较。比较输入 reg (r4) 和 5 如果相等则分支到地址 18。如果不相等继续。
如果不相等则
c: 00001025 move $2,$0
10: 03e00008 jr $31
14: 00000000 nop
在返回寄存器 r2 中输入 0 并返回。这条路径相当于
r = 0;
return(r);
如果等于 5 则
18: 24020006 li $2,6
1c: 03e00008 jr $31
20: 00000000 nop
将 6 放入 r2 并返回
对于这个示例 C 代码,编译器对解决方案非常暴力,除了不会产生更多分支以具有单个退出点(非典型)。
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);
}
有时你会看到工具生成一个跳转表,这取决于架构和其他因素,在这种情况下不会发生但如果你有 switch(b&3) 然后是四种可能的情况,我试过和 gcc没有做跳转表。
但真正的开关是什么?在这种情况下以及在所有情况下,它只不过是 if (括号中的参数,在这种情况下只是 b 本身) b is 5 else of b is 7 then。 switch 是一个 if-then-else 树,通常编译器会费心去实现。
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,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,3
34: 03e00008 jr $31
38: 00000000 nop
r = a
4: 00801025 move $2,$4
如果 b == 5 那么
0: 24030005 li $3,5
8: 10a30009 beq $5,30 <fun+0x30>
c: 00000000 nop
r+=3 并返回
30: 24820003 addiu $2,3
34: 03e00008 jr $31
38: 00000000 nop
(else) 如果 b==7
10: 24030007 li $3,28 <fun+0x28>
18: 00000000 nop
r ^=3 并返回
1c: 38820003 xori $2,0x3
20: 03e00008 jr $31
24: 00000000 nop
else 返回(r 被设置为一个前面)
28: 03e00008 jr $31
2c: 00000000 nop
所以它是一个简单的 if-then-else 树,带有一个非蛮力乱序的东西,r = a 被放置在 if b == 5 混合在一起的中间。
unsigned int fun ( unsigned int a )
{
unsigned int r;
r = 0;
if(a<5)
{
r = 3;
}
return(r);
}
00000000 <fun>:
0: 2c840005 sltiu $4,5
4: 14800004 bnez $4,$0
10: 03e00008 jr $31
14: 00000000 nop
18: 24020003 li $2,3
1c: 03e00008 jr $31
20: 00000000 nop
因为 mips 的工作原理或者至少是我编译的 mips
如果小于无符号则设置
0: 2c840005 sltiu $4,5
由于 C 的编写方式,我们实际上可以使用 if 小于问题丢弃 a 变量。因此,如果 r4 (a) 小于 5,则“设置” r4(非零)
所以现在小于变成了一个相等或不相等的问题
if(r4 is not equal to zero) 结合上面的意思是如果a小于5则
4: 14800004 bnez $4,18 <fun+0x18>
8: 00000000 nop
返回 3
18: 24020003 li $2,3
1c: 03e00008 jr $31
20: 00000000 nop
否则返回0
c: 00001025 move $2,$0
10: 03e00008 jr $31
14: 00000000 nop
Mips 不像大多数其他指令集那样喜欢/使用标志。大多数其他人会有一个比较指令,它执行减法并设置一堆标志,但不将减法存储到寄存器中,然后后续指令将使用这些标志。 mips 使用无标志的理念,因此进行比较并在同一指令中对其进行操作。例如另一个架构:
00000000 <fun>:
0: e3500004 cmp r0,#4
4: 93a00003 movls r0,#3
8: 83a00000 movhi r0,#0
c: e12fff1e bx lr
比较a和4然后如果小于或相同r = 3如果更高r = 0并返回。这在某种程度上也是非常不典型的,因为这里显示的这个指令集 (arm) 允许按指令条件执行,而不仅仅是分支是有条件的,而 mov 和 add 等不是。
这是更典型的
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
这几乎是一对一的蛮力
r = 0
0: 0a00 clr r0
比较a(在堆栈中传入)与4
2: 2d97 0002 0004 cmp 2(sp),$4
分支如果低于或与地址 c 相同:
8: 8301 blos c <_fun+0xc>
如果大于等于 5 则返回(r = 0)
a: 0087 rts pc
如果小于5(小于等于4)则返回3
c: 15c0 0003 mov $3,r0
10: 0087 rts pc
(目的地在右边这里 mov $3,r0 表示 r0 = 3。$ 在这里表示常量)
,没想到我会再次使用这些知识!希望这会有所帮助。
查看参考表并了解说明的作用会有所帮助。通常 if
和 else
可以用“如果相等则分支”(beq)或“如果不相等则分支”(bne)来模拟。请查看以下参考以了解这些说明。
此外,while
和 switch
使用相同的指令 - 只需考虑代码应该如何流动。
查看此参考资料,了解有关如何使用说明的更多详细信息,以及我未提及的其他内容。我会提到大部分指令应该使用寄存器,加载/保存字,分支,基本跳转,数学等。
https://inst.eecs.berkeley.edu/~cs61c/resources/MIPS_help.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。