首页 > 解决方案 > RISCV函数使用寄存器

问题描述

使用 RISCV 的这段代码的返回值是多少,
考虑 c 的形式是 int fun(int n)

fun: 
addi s0, zero, 0 
addi s1, zero, 1 
add t0, zero, a0
loop: 
beq s0, t0, exit 
add s1, s1, s1 
addi s0, s0, 1 
jal zero, loop 
exit: 
add a0, zero, s1 
jalr zero, 0(ra)

标签: assemblyriscv

解决方案


有时,在分析汇编时,直接了解 C 中发生的事情可能会有所帮助,然后简化:

int fun(int n) {
    int s0 = 0;
    int s1 = 1;
    int t0 = n; // n is in a0

loop:
    if (s0 == t0) {
        goto loop_exit;
    }

    s1 = s1 + s1;
    s0 = s0 + 1;

    goto loop;

loop_exit:
    return s1; // Returns in a0
}

我们可以看到t0不需要复制到,我们可以n直接使用。此外,这个goto结构看起来很像一个while循环,在开始时对循环进行条件检查。

int fun(int n) {
    int s0 = 0;
    int s1 = 1;

    while (s0 != n) {
        s1 += s1;
        s0 += 1;
    }

    return s1;
}

我们现在可以看到s1它将从 1 开始,然后翻倍n。我们可以重写给出描述性的名称,并用whilea代替for

int fun(int n) {
    int value = 1;

    for (int counter = 0; counter != n; counter += 1) {
        value += value;
    }

    return value;
}

由于编译器的优点,这三组代码实际上生成了相同的程序集(在那个特定的编译器上,在我写这篇文章的时候)。


n小于 的精度时int,此函数表现为左移 1n位。

在这种非边缘情况下,fun等价于:

int fun(int n) {
    return 1 << n;
}

如果n至少是 的精度int,那么您会遇到有符号整数溢出,这会导致实现定义的行为。


推荐阅读