【问题标题】:Going from C code to RISC-V assembly code从 C 代码到 RISC-V 汇编代码
【发布时间】:2023-04-10 14:09:05
【问题描述】:

我有这个练习

将以下 C 代码翻译成 RISC-V 汇编代码。假设 a、b、i 和 j 的值分别在寄存器 x5、x6、x7 和 x29 中。另外,假设寄存器 x10 保存着数组 D 的基地址。

for(i=0; i<a; i++){
    for(j=0; j<b; j++){
        D[4*j] = i + j;
    }
}

我也有 cmets 的解决方案

Loop1:
    addi x7, x0, 0      // i = 0
    bge  x7, x5, ENDi   // while i < a
    addi x30, x10, 0    // x30 = &D[0]
    addi x29, x0, 0     // j = 0
Loop2:
    bge x29, x6, ENDj   // while j < b
    add x31, x7, x29    // x31 = i + j
    sd  x31, 0(x30)     // D[4*j] = x31
    addi x30, x30, 32   // x30 = &D[4*(j+1)]
    addi x29, x29, 1    // j++
    jal  x0,  LOOP2
ENDj:
    addi x7, x7, 1      // i++
    jal  x0, LOOP1
ENDi:

我不明白的地方

sd  x31, 0(x30)     // D[4*j] = x31
addi x30, x30, 32   // x30 = &D[4*(j+1)]

sd x31, 0(x30) 不是表示我将 x31 的值存储在数组 30 的第 0 位吗?突然的4*j是从哪里来的?

addi x30, x30, 32 不是表示 x30 = x30+32 吗?第一个循环中没有定义 x30 = &D[0] 吗? j怎么突然接触到x30了?

【问题讨论】:

    标签: c assembly riscv


    【解决方案1】:

    这等价于:

    for(int64_t i=0; i<a; i++){
        int64_t* x30 = &D[0];
        for(int64_t j=0; j<b; j++){
            *x30 = i + j;
            x30 += 4; // increment by 4 elements
        }
    }
    

    x30 在循环中用作“当前指针”。它指向 D 数组中的相关元素。它被初始化为第一个元素,并以 4 个元素为步长递增,这模拟了 4*j 部分。由于您的元素是 64 位 8 字节,因此要增加 4 个元素,指针的基础地址应增加 4*8=32 字节。

    维护当前指针通常比每次都重新计算更有效,尤其是在 RISC-V 中,因为您不能有寄存器偏移量(没有str x31, [x30, x29])。

    【讨论】:

    • 感谢您的回答,但我仍然感到困惑。您能详细说明代码sd x31, 0(x30) 的作用吗?因为我在解决方案中看不到代码和注释的关系。
    • @Carl sd x31, 0(x30) 字面意思是将 x31 存储在 x30 中的地址,所以 C 中的 *x30 = x31 存储到 x30 指向的元素,相当于 x30[0] = x31 (* 对于指针和 [] 用于数组)。
    • @Carl x30 与 j 同时递增以在数组中前进。使用 j,访问将是 D[0]D[4]D[8]... D 的索引每个循环增加 4 个元素,因此 x30 从 &D 开始,每个循环增加 4 个元素是等效的.基本上,它正在做D[0]; D+=4D[0]; D+=4D[0]; D+=4。当您增加最初指向 D[0] 的 x30 时,您使其指向以下元素,因此 x30 = &amp;D[0]x30 += 4 表示 x30 指向 D[4]。
    • @Carl 如果 D 是一个数组,你就不能真正做到D+=4,但在 C(和汇编)中,数组和指针之间几乎没有区别。如果您改用指针,如int64_t* x30 = &amp;D[0];,则x30 指向D[0],并且执行x30 += 4; 每个循环将允许您访问D[0]D[4]D[8]... 每个数组元素在内存中是连续的。因此,将地址/指针指向第一个元素,然后将其递增将允许您访问数组中的下一个元素。
    • @Carl:将D[j*4]优化成ptr+=4与“强度降低”有关。 en.wikipedia.org/wiki/Strength_reduction。您仅用指针增量替换循环中的移位/添加地址生成计算。如果乘数不是 2 的简单幂(因为班次仍然相对便宜,即没有那么“强”),则更重要的是,但它仍然是将多个操作减少到一个的情况。
    猜你喜欢
    • 2022-11-20
    • 1970-01-01
    • 1970-01-01
    • 2012-03-04
    • 1970-01-01
    • 1970-01-01
    • 2018-05-07
    • 2011-08-27
    • 2021-07-18
    相关资源
    最近更新 更多