我正在学习如何将 RISC-V 汇编代码转换为 C,但我不明白这种转换。我有几个问题:
t1
被初始化为 6
而不是 0
?while (t1 == t0)
。看来这种相反的技术被用于 if (t1 ==0)
。为什么?addi t0, t0, -1
而不是sub?非常感谢任何见解。我的课堂环境节奏很快,提问不太友好,所以我在课堂上提问时很紧张。
main:
# Tests simple looping behavior
li t0, 60
li t1, 0
loop:
addi t1, t1, 5
addi t0, t0, -1
bne t1, t0, loop
bne t1, zero, success
failure:
li a0, 0
li a7, 93
ecall
success:
li a0, 42
li a7, 93
ecall
这是我得到的答案:
int main(){
int t0 = 60;
int t1 = 6;
while(t1 != t0){
t1 = t1 + 5;
t0 = t0 - 1;
}
if(t1 == 0){
int a0 = 0;
return 0;
}else{
int a0 = 42;
return 0;
}
}
我们被教导在将 C 转换为 RISC-V 时使用 bne/beq 的反义词,因此令人困惑的是为什么此 RISC-V 程序集的“正确”C 转换会包含
while (t1 != t0)
。
初始化 t1 到 6 对我来说也没有任何意义。看起来很明显用'li t1, 0'加载到0。
C 与 RISC-V 组件不太匹配。
你是对的,asm 显然是
t1 = 0
而不是 t1 = 6
。如果此材料被打印出来并扫描回来或其他什么,可能会出现拼写错误或 OCR 错误。
此外,那些
ecall
是 _exit(0)
和 _exit(42)
,而不是 return
陈述。 asm 不使用其返回地址。
不过,其余部分看起来都不错。自己尝试一下,单步执行 asm 与 C 程序,分别观察寄存器或变量的变化。应该清楚的是,执行会停留在循环中,直到它们相等,即当它们不相等时。
像这样的惯用 asm 循环最直接的 C 表示是
do{}while(t1 != t0);
,条件位于底部,就像 asm 一样。 (将其显示为 for
或 while
循环取决于初始化器使条件为 true,因此循环体至少运行一次迭代。)请参阅 为什么循环总是编译为“do...while”样式(尾跳)?
尝试更改汇编以使用
sub
并立即使用 -1
。大多数汇编器会拒绝这一点,因为 RISC-V 没有 subi
,除非作为伪指令。它没有标志/条件代码寄存器,因此减法与加负数完全相同,并且 RISC-V 始终对立即操作数进行符号扩展。它从 subi
操作码中获得的唯一好处是能够通过 +4096 .. -4095
来更改值,而不是 addi
的 -4096 .. +4095
范围及其 12 位立即数。这显然不值得再设置一个操作码。