学习 RISC-V 汇编并需要转换 C 循环的帮助

问题描述 投票:0回答:1

我正在学习如何将 RISC-V 汇编代码转换为 C,但我不明白这种转换。我有几个问题:

  1. 为什么
    t1
    被初始化为
    6
    而不是
    0
  2. 我们使用 bne 来比较 t1 和 t2,但我们被教导使用相反的方法,这意味着 C 代码将是
    while (t1 == t0)
    。看来这种相反的技术被用于
    if (t1 ==0)
    。为什么?
  3. 最后,为什么用
    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 assembly reverse-engineering riscv
1个回答
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 位立即数。这显然不值得再设置一个操作码。

© www.soinside.com 2019 - 2024. All rights reserved.