gpt4 book ai didi

assembly - 在 GCC 内联汇编中影响内存操作数寻址模式的早期破坏者的不正确行为的具体示例?

转载 作者:行者123 更新时间:2023-12-04 04:26:55 25 4
gpt4 key购买 nike

以下摘自GCC manual's Extended Asm docs , 关于使用 asm 在 C 中嵌入汇编指令关键词:

The same problem can occur if one output parameter (a) allows aregister constraint and another output parameter (b) allows a memoryconstraint. The code generated by GCC to access the memory address inb can contain registers which might be shared by a, and GCC considersthose registers to be inputs to the asm. As above, GCC assumes thatsuch input registers are consumed before any outputs are written. Thisassumption may result in incorrect behavior if the asm statementwrites to a before using b. Combining the ‘&’ modifier with theregister constraint on a ensures that modifying a does not affect theaddress referenced by b. Otherwise, the location of b is undefined ifa is modified before using b.


斜体句子表示如果 asm 语句写入 a,可能存在“不正确的行为”。使用前 b .
我无法弄清楚这种“不正确的行为”是如何发生的,所以我希望有一个具体的 asm 代码示例来演示“不正确的行为”,以便我可以深入理解这一段。
当两个这样的 asm 代码并行运行时,我可以察觉到问题,但上面的段落没有提到多处理场景。
如果我们只有一个单核的CPU,能否请您给出一个可能产生这种错误行为的asm代码,即修改 a影响 b 引用的地址使得 b的位置未定义。
我唯一熟悉的汇编语言是 Intel x86 汇编,因此请让示例针对该平台。

最佳答案

考虑以下示例:

extern int* foo();
int bar()
{
int r;

__asm__(
"mov $0, %0 \n\t"
"add %1, %0"
: "=r" (r) : "m" (*foo()));

return r;
}
通常的调用约定将返回值放入 eax登记。因此,编译器很有可能决定使用 eax自始至终,避免不必要的复制。生成的程序集可能如下所示:
        subl    $12, %esp
call foo
mov $0, %eax
add (%eax), %eax
addl $12, %esp
ret
请注意 mov $0, %eaxeax在下一条指令尝试使用它来引用输入参数之前,因此此代码将崩溃。使用早期的 clobber,您会强制编译器选择不同的寄存器。就我而言,结果代码是:
        subl    $12, %esp
call foo
mov $0, %edx
add (%eax), %edx
addl $12, %esp
movl %edx, %eax
ret
编译器可以改为移动 foo() 的结果进入 edx (或任何其他免费注册),像这样:
        subl    $12, %esp
call foo
mov %eax, %edx
mov $0, %eax
add (%edx), %eax
addl $12, %esp
ret
这个例子对输入参数使用了内存约束,但这个概念同样适用于输出。

关于assembly - 在 GCC 内联汇编中影响内存操作数寻址模式的早期破坏者的不正确行为的具体示例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67645020/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com