Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
重写GCC内联程序集以不需要volatile或内存缓冲_C_Gcc_Arm_Inline Assembly - Fatal编程技术网

重写GCC内联程序集以不需要volatile或内存缓冲

重写GCC内联程序集以不需要volatile或内存缓冲,c,gcc,arm,inline-assembly,C,Gcc,Arm,Inline Assembly,是否可以重写或改进此函数,使其内联程序集中不需要volatile或通用内存缓冲 // do stuff with the input Foo structure and write the result to the // output Bar structure. static inline void MemFrob(const struct Foo* input, struct Bar* output) { register const Foo* r0 asm("r0") = in

是否可以重写或改进此函数,使其内联程序集中不需要volatile或通用内存缓冲

// do stuff with the input Foo structure and write the result to the 
// output Bar structure.
static inline void MemFrob(const struct Foo* input, struct Bar* output) {
    register const Foo* r0 asm("r0") = input;
    register Bar* r1 asm("r1") = output;

    __asm__ __volatile__(
        "svc #0x0f0000 \n\t"
        : "+r" (r0), "+r" (r1)
        :
        : "r2", "r3", "cc", "memory"
        );
}
对于这种特定情况,目标平台是一个ARM7系统,代码正在使用GCC 5.3.0进行编译。正在执行的系统调用与C函数调用具有相同的调用约定。经过一些尝试和错误,我已经达到了上面的“工程”,但我还没有信心,它是正确的,并将始终工作,受突发奇想和幻想的优化编译器

我希望能够删除“内存”阻塞器,并准确地告诉GCC将修改哪个内存,但GCC扩展Asm文档讨论了如何将值分配给特定寄存器,然后是内存约束,但不讨论它们是否可以组合。到目前为止,从上述示例中删除“memory”clobber可能会导致GCC在后续代码中不使用输出

我还希望能够在不使用输出的情况下删除volatile。但到目前为止,从上述示例中删除volatile会导致GCC根本不发出程序集


添加额外的内联程序集来手动将系统调用参数移动到r0/r1中,或者通过将代码移动到外部编译单元来取消内联,这是我宁愿避免的浪费性解决方法。

长话短说:这就是
“m”
约束的作用。通常,如果您正在使用
volatile
\uuuuuuvolatile\uuuuuu
,与
asm
一起使用,这是因为您的代码中存在错误。编译器的主要工作之一是流分析,因此只要您为它提供足够的信息来进行正确的流分析,一切都将正常工作

以下是一个固定版本:

void MemFrob(const struct Foo* input, struct Bar* output) {
    register const Foo* r0 asm("r0") = input;
    register Bar* r1 asm("r1") = output;
    __asm__ (
        "svc #0x0f0000"
        : "=m"(*r1) // writes data to *output (but does not read)
        : "m"(*r0), // reads data in *input
          "l"(r0), "l"(r1) // This is necessary to ensure correct register
        : "r2", "r3", "cc"
        );
}
您可以在(
-O2
编译器选项推荐)上测试它。结果如下:

svc #0x0f0000
bx lr
显然,当内联时,它应该减少到只有一条指令

不幸的是,在使用内联ARM汇编时,我无法理解如何指定特定的寄存器,除了上面的方法有点笨拙。

1)是的,可以有一个约束是寄存器,另一个是内存,是的,两个约束可以重叠。2) 如果没有volatile,gcc将asm视为计算
r0
r1
的新值的方法。但是,由于优化器可以看到变量
r0
r1
在asm之后超出范围之前不会再次使用,因此asm被丢弃。