[英]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
"=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 意味着如果没有使用任何结果,则可以消除死代码"=m"(*(char (*)[100])buffer)
can be used to get the constraint on the entire buffer."=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.