简体   繁体   English

ASM 约束副作用

[英]ASM constraints side effects

I'm having a hard time understanding some effects of some specific constraints in GCC for inline-assembly.我很难理解 GCC 中某些特定约束对内联汇编的一些影响。

I the below example, if I run with "=X" on the output and "X" on all the inputs, the 2 prints output我在下面的例子中,如果我在输出上用“=X”运行,在所有输入上用“X”运行,2打印输出

0x562f39629260, 100 0x562f39629260, 100

0x14, 100 0x14, 100

Which indicates that the pointer to the buffer that I allocated has changed.这表明指向我分配的缓冲区的指针已更改。 Leading to a Segfault is a try to read the content of the buffer after my assembly code.导致段错误是尝试在我的汇编代码之后读取缓冲区的内容。

On the contrary, If i put "+X" on the output or "m" in the inputs then the addresses stay the same, the prints output:相反,如果我在输出中放置“+X”或在输入中放置“m”,则地址保持不变,打印输出:

0x55571bb83260, 100 0x55571bb83260, 100

0x55571bb83260, 100 0x55571bb83260, 100

And I can safely read my buffer without segfaulting.而且我可以安全地读取我的缓冲区而不会出现段错误。

I don't understand how or why this pointer should/could be modified?我不明白如何或为什么应该/可以修改这个指针? Is there a way to safely choose constraints?有没有办法安全地选择约束? The gcc online documentation does not give much insight on this. gcc 在线文档对此没有给出太多见解。

Thanks a lot,非常感谢,

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 $1, (%%rcx) \n"
    "add $1, %%rcx \n"
    "sub $1, %%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;
}

The = in =X means this is an OUTPUT ONLY constraint (as opposed to an update constraint with + ).==X手段,这是一仅输出约束(而不是更新约束带+ )。 This means that the assembly code is expected to to write something to the operand (to %0 ) and that will ben the value that is output.这意味着汇编代码应该向操作数(到%0 )写入一些内容,这将成为输出的值。 But since your assembler code never writes to %0 , you get whatever garbage happens to be in that location (probably a register that the register allocator picked).但是由于您的汇编代码从不写入%0 ,您会得到该位置发生的任何垃圾(可能是寄存器分配器选择的寄存器)。

Try adding a mov %%rcx,%0 line to the asm code to see what actually happens.尝试在 asm 代码中添加mov %%rcx,%0行以查看实际发生的情况。

Most likely what you really want is something more like:很可能你真正想要的是更像:

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

Note that this leaves buffer pointing after the inserted values (at the end of the buffer) -- not clear if that is what you want.请注意,这会在插入的值之后(在缓冲区的末尾)留下buffer指向——不清楚这是否是你想要的。 You can do the same with size, making it even simpler:你可以对 size 做同样的事情,让它更简单:

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

Though it would be even simpler (and better for the optimizer) to not use asm at all:尽管根本不使用 asm 会更简单(并且对优化器更好):

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

So to summarize all the comments below, what you might want is something like:所以总结一下下面的所有评论,你可能想要的是:

long size = 100;
char buffer[100];
char *temp;
__asm__(
"loop: \n"
"movb $1, (%[out]) \n"
"add $1, %[out] \n"
"sub $1, %[size] \n"
"jnz loop \n"
: [out]"=r"(temp), [size]"+X"(size), "=m"(buffer) //outputs
: "0"(buffer) // inputs
)  // no clobbers
  • using an "=m" constraint on the entire buffer instead of a memory clobbers and volatile means that it can be dead-code eliminated if none of the results are used在整个缓冲区上使用"=m"约束而不是内存破坏和 volatile 意味着如果没有使用任何结果,则可以消除死代码
  • using a temp for the pointer being advanced over the buffer means the original buffer (start) value can be preserved.对在缓冲区上前进的指针使用临时值意味着可以保留原始缓冲区(起始)值。
  • if you must use malloc for the buffer "=m"(*(char (*)[100])buffer) can be used to get the constraint on the entire buffer.如果必须对缓冲区使用 malloc, "=m"(*(char (*)[100])buffer)可用于获取对整个缓冲区的约束。

Hoever, I stand by my earlier comment that writing it without asm is better;但是,我坚持我之前的评论,即不使用 asm 编写它会更好; it's simpler and easier to understand and the compiler's optimizer will probably vectorize it for you.它更简单,更容易理解,编译器的优化器可能会为您向量化它。

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

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