繁体   English   中英

RISC-V 内联汇编

[英]RISC-V inline assembly

我对内联汇编很陌生,所以我需要你的帮助来确保我正确使用它。 我需要在使用 Risc-v 工具链编译的 C 代码中添加汇编代码。 请考虑以下代码:

int bar = 0xFF00;

int main(){
    volatile int result;
    int k;
    k = funct();
    int* ptr;
    ptr = &bar;
    asm volatile (".insn r 0x33, 0, 0, a4, a5, a3":
                       "=m"(*ptr), "=r"(result):
                       [a5] "m"(*ptr), [a3] "r"(k) :
                      );
        
    }
...

我想要做的是bar = bar+k 实际上,我想更改bar所在的内存位置的内容。但是我编写的代码获取了bar的地址并将其添加到k 有人知道问题出在哪里吗?

不幸的是,您误解了语法。

在汇编程序字符串中,您可以使用%0%1引用参数,其中数字是传递给asm指令的第 n:th 个参数。 或者,您可以使用符号名称%[myname] ,它引用[myname]"r"(k)形式的参数。

请注意,符号名称与使用数字相同,名称本身并不意味着任何东西。 在您的示例中,给人的印象是您正在强制代码使用特定的处理器寄存器。 (如果你真的需要使用它,还有另一种语法。)

例如,如果您编写如下内容:

int bar = 0xFF00;

int main(){
    volatile int result;
    int k;
    k = funct();
    int* ptr;
    ptr = &bar;
    asm volatile (".insn r 0x33, 0, 0, %[res], %[res], %[ptr]":
                  [res]"+r"(result) : [ptr]"r"(ptr));
}

IAR 编译器将发出以下内容。 如您所见,已为a0分配了result变量(使用符号名称res ),为a1分配了变量ptr (此处,符号名称与变量名称相同)。

   \   000014 0001'2503    lw        a0, 0x0(sp)
   \   000018 0000'05B7    lui       a1, %hi(bar)
   \   00001C 0005'8593    addi      a1, a1, %lo(bar)
   \   000020 00B5'0533    .insn r 0x33, 0, 0, a0, a0, a1
   \   000024 00A1'2023    sw        a0, 0x0(sp)

您可以在“IAR C/C++ Development Guide Compiling and linking for RISC-V”一书的“Assembler Language Interface”一章中阅读有关 IAR 内联汇编语法的更多信息。 这本书以 PDF 格式提供,您可以从 IAR Embedded Workbench 中访问它。

根据您的问题中提供的代码片段,我尝试使用 IAR C/C++ Compiler for RISC-V V3.10 编写以下代码:

int funct();
int funct() { return 0xA5; }

int bar = 0xFF00;

int main() {
    int k = funct();
    int* ptr = &bar;
#if defined(__ICCRISCV__)
    __asm volatile (".insn r 0x33, 0, 0, a3, a3, a4"
                    : "=a3"(*ptr)
                    : "a3"(*ptr), "a4"(k)
                    : "memory" );
#endif
}

在这种情况下, ADD指令是寄存器到寄存器指令。 在这种情况下, a3被用作输入和输出, .insn指令生成的指令是: add a3,a3,a4 ,实际上是*ptr = *ptr + k

IAR 编译器允许在内联汇编中显式选择寄存器,如此所述。

正如 @PeterCordes 在评论中指出的那样,GCC 不能直接引用要使用的寄存器,因为它提供了一组不同的约束,因此这里可能需要一个更通用的解决方案。

memory clobber 不是强制性的,尽管它很有用,因为它警告编译器全局内存将受到指令的影响。

此外,在可移植性方面, asm关键字在 C++ 中得到了更正式的支持。 尽管许多 C 编译器会接受它,但如果指定了严格的一致性,有些编译器会立即拒绝它。 因此,最兼容的选择是__asm

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM