ASM 约束副作用

ASM constraints side effects

我很难理解某些特定的效果 GCC 中对内联汇编的约束。

在下面的示例中,如果我 运行 在输出上使用“=X”并且在所有输入上使用 "X",则 2 打印输出

0x562f39629260, 100

0x14, 100

这表明指向我分配的缓冲区的指针已更改。导致段错误的是尝试读取缓冲区的内容 在我的汇编代码之后。

相反,如果我在输出中输入“+X”或在输入中输入"m",那么 地址保持不变,打印输出:

0x55571bb83260, 100

0x55571bb83260, 100

而且我可以安全地读取我的缓冲区而不会出现段错误。

我不明白这个指针 should/could 是如何或为什么被修改的? 有没有办法安全地选择约束? gcc 联机文档 对此没有给出太多见解。

非常感谢,

int main() {
    long size = 100;
    char * buffer = (char*)malloc(size*sizeof(char));

    printf("%p, %d\n",buffer, size);

    __asm__(
    "mov %[out], %%rcx \n"
    "mov %[size], %%rbx \n"
    "loop: \n"
    "movb , (%%rcx) \n"
    "add , %%rcx \n"
    "sub , %%rbx \n"
    "jnz loop \n"
    : "=X"(buffer) //outputs
    : [out]"X"(buffer), [size]"X"(size) //inputs
    : "rbx", "rcx" //clobbers
    );

    printf("%p, %d\n",buffer, size);

    return 0;
}

=X 中的 = 表示这是一个 OUTPUT ONLY 约束(与 + 的更新约束相反)。这意味着汇编代码应该向操作数(%0)写入一些东西,这将是输出的值。但是由于您的汇编程序代码从不写入 %0,因此您会得到恰好位于该位置的任何垃圾(可能是寄存器分配器选择的寄存器)。

尝试在 asm 代码中添加 mov %%rcx,%0 行以查看实际发生的情况。

很可能您真正想要的是:

__asm__ volatile (
"mov %[size], %%rbx \n"
"loop: \n"
"movb , (%[out]) \n"
"add , %[out] \n"
"sub , %%rbx \n"
"jnz loop \n"
: [out]"+r"(buffer) //outputs
: [size]"X"(size) //inputs
: "rbx", "memory" //clobbers
);

请注意,这会使 buffer 指向插入的值之后(在缓冲区的末尾)——不清楚这是否是您想要的。你可以对大小做同样的事情,让它变得更简单:

__asm__ volatile (
"loop: \n"
"movb , (%[out]) \n"
"add , %[out] \n"
"sub , %[size] \n"
"jnz loop \n"
: [out]"+r"(buffer), [size]"+X"(size) //outputs
: //inputs
: "memory" //clobbers
);

虽然根本不使用 asm 会更简单(对优化器来说更好):

do { *buffer++ = ''; } while (--size);

所以总结下面的所有评论,您可能想要的是:

long size = 100;
char buffer[100];
char *temp;
__asm__(
"loop: \n"
"movb , (%[out]) \n"
"add , %[out] \n"
"sub , %[size] \n"
"jnz loop \n"
: [out]"=r"(temp), [size]"+X"(size), "=m"(buffer) //outputs
: "0"(buffer) // inputs
)  // no clobbers
  • 在整个缓冲区上使用 "=m" 约束而不是内存破坏和易失性意味着如果使用 none 结果可以消除死代码
  • 对在缓冲区上前进的指针使用临时意味着可以保留原始缓冲区(起始)值。
  • 如果必须对缓冲区使用 malloc "=m"(*(char (*)[100])buffer) 可用于获取整个缓冲区的约束。

但是,我坚持我之前的评论,即不使用 asm 编写它更好;它更简单易懂,编译器的优化器可能会为您对其进行矢量化处理。