在gcc的内联汇编中,我能修改输入操作数吗?

4
我们知道,如果我将%eax设置为输入,则无法将其包含在破坏寄存器列表中。因此,我的问题是,在汇编代码中修改%eax的值而没有在破坏列表中声明是否合法?
__asm__ __volatile__("inc %0" :: "a"(num) : "%eax"); // illegal
__asm__ __volatile__("inc %0" :: "a"(num));       // Can I modify %eax?

你的代码可以编译和汇编,但在运行时可能会以奇怪的方式崩溃,或者有时不会崩溃,这取决于周围的代码和优化选项。这意味着单元测试不足以证明内联汇编的正确性或安全性。 - Peter Cordes
1个回答

6
不是的,如果汇编代码更改了输入寄存器,它也必须在约束中使用“+”而不是“=”列出作为输出寄存器或输入/输出寄存器。
例如:
__asm__ __volatile__("..." : "+r"(num));
__asm__ __volatile__("..." : "=a"(dummy) : "a"(num));
__asm__ __volatile__("..." : "=r"(dummy) : "0"(num));

第一个例子将num同时指定为输入和输出。这将覆盖先前的num值,如果操作数被破坏而不是设置为有用的值,则可能是不可取的。
第二个例子明确使用eax作为输入和输出。它将输出指向一个dummy变量,以避免破坏实际的输入变量num
第三个例子使用虚拟输出,以避免修改num,并且还避免明确指定eax,允许编译器选择要使用的寄存器。 "0"约束告诉编译器对于此输入操作数,使用与操作数0相同的寄存器。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接