【问题标题】:Unexpected GCC inline ASM behaviour (clobbered variable overwritten)意外的 GCC 内联 ASM 行为(被破坏的变量被覆盖)
【发布时间】:2014-12-21 11:05:12
【问题描述】:

在我的电脑上,编译后的可执行文件省略了在循环顶部执行“mov %2, %%ax”

当 "add %1, %%ax" 未注释时。

有人要仔细检查或评论吗?

#include <stdio.h>

int main() {

short unsigned result, low ,high;

    low  = 0;
    high = 1;

    __asm__ (   
        "movl $10, %%ecx \n\t"

        "loop: mov  %2, %%ax \n\t"

//      "add    %1, %%ax \n\t"      // uncomment and result = 10
        "mov    %%ax, %0     \n\t"

        "subl   $1, %%ecx \n\t"                 
        "jnz loop"                              
        : "=r" (result)
        : "r" (low) , "r" (high)
        : "%ecx" ,"%eax" );        

    printf("%d\n", result);  
    return 0;
}

遵循生成的程序集

movl $1, %esi
xorl %edx, %edx
/APP
movl $10 ,%ecx 

loop: mov %si, %ax 
mov  %dx, %bx 
add %bx, %ax 
mov %ax, %dx     
subl $1, %ecx 
jnz loop  
/NO_APP

感谢 Jester 的解决方案:

    : "=&r" (result)        // early clober modifier

【问题讨论】:

标签: gcc assembly inline-assembly i386


【解决方案1】:

GCC 内联汇编是高级编程,有很多陷阱。确保您确实需要它,并且不能用独立的汇编模块或使用内部函数的 C 代码替换它。或向量支持。

如果您坚持使用内联汇编,您应该准备至少查看生成的汇编代码并尝试从中找出任何错误。显然,编译器不会省略您写入 asm 块的任何内容,它只是替换参数。如果您查看生成的代码,您可能会看到如下内容:

    add    %dx, %ax
    mov    %ax, %dx

显然编译器选择了dx 作为参数01。允许这样做,因为默认情况下它假定输入参数在写入任何输出之前被消耗。为了表明情况并非如此,您必须使用early clobber modifier 作为输出操作数,因此它看起来像"=&amp;r"

PS:即使内联汇编似乎可以工作,它也可能有隐藏的问题,当编译器碰巧做出其他选择时,它可能会在另一天困扰你。你真的应该避免它。

【讨论】:

  • 为您的答案投票。我仍在试图弄清楚 %1%0 语法在做什么。欢迎提供指向资源以了解这些内容的指针。
  • 感谢您的解决方案!我还没有找到如何在 minGW 上启动汇编程序。我在早期测试中使用内联汇编来了解内部循环的运行速度。我将研究独立的 ASM 模块和其他指针。
  • @User.1 如果您正在寻找有关 gcc 的内联 asm 的文档,我建议您直接访问源代码:gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
  • 你关于应该避免内联汇编的说法让我感到困惑。当您只想优化汇编中的几个函数并且希望这些函数内联时,还有什么其他选择?例如,假设您想要使用 add 和 adc 进行 256 位大整数加法。您显然希望内联此函数。
  • @Zboson:我认为他的意思是“当你可以用另一种方式时避免”,我同意。在测试条件下不显示的内联汇编很容易出错。但是,在这种情况下,没有其他方法可以让编译器发出add/adc/adc/adc。如果你写high += hiAdd + (low &lt; lowAdd)之类的东西,gcc和clang会发出adc,但只有在实际执行cmp来设置CF之后,因为它没有意识到add会以同样的方式设置CF。 goo.gl/Ea17p8
猜你喜欢
  • 1970-01-01
  • 2015-02-19
  • 2021-03-03
  • 1970-01-01
  • 2020-01-08
  • 1970-01-01
  • 2012-07-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多