意外的GCC内联汇编行为(重挫变量覆盖) [英] Unexpected GCC inline ASM behaviour (clobbered variable overwritten)

查看:208
本文介绍了意外的GCC内联汇编行为(重挫变量覆盖)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的电脑,执行编译的可执行遗漏MOV%2 %%斧的循环顶部

在添加%1 %%斧注释。

送人doublecheck或评论?

 的#include<&stdio.h中GT;诠释主(){短期无符号结果,低,高,    低= 0;
    高= 1;    __asm​​__(
        MOVL $ 10 %% ECX \\ n \\ t的        循环:MOV%2 %%斧\\ n \\ t的//添加%1,斧%% \\ n \\ t//取消注释和结果= 10
        MOV AX %%,%0 \\ n \\ t的        subl $ 1,ECX %% \\ n \\ t的
        JNZ循环
        := R(结果)
        :R(低),R(高)
        :%ecx中,%eax中);    的printf(%d个\\ N,结果);
    返回0;
}

遵循生成的程序集

  MOVL $ 1%ESI
xorl%EDX,EDX%
/ APP
MOVL $ 10%ECX循环:MOV%SI,斧头%
MOV%DX,BX%
添加%BX,斧头%
MOV AX%,%DX
subl $ 1,ECX%
JNZ循环
/ NO_APP

由于弄臣解决方案:

 :=&安培; R(结果)//早clober修改


解决方案

GCC内联汇编的高级编程,有很多陷阱。请确保你真正需要它,而且不能与独立的组装模块,或C $ C $使用内部函数c更换它。或矢量支持。

如果你坚持内联汇编,你应该是prepared至少看生成的程序集code,并试图从那里找出任何错误。显然,编译器不会忽略你写到ASM块什么,它只是代替了争论。如果你看一下生成的code,你可能会看到这样的事情:

 添加%DX,斧头%
    MOV AX%,%DX

显然,编译器挑 DX 这两个参数 0 1 。这是允许这样做,因为默认情况下它假定写入任何输出前的输入参数被消耗。要发出信号,这是不是这种情况,您必须使用早期撞修改为输出操作数,因此,它看起来像=再现性。

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

On my computer, the compiled executable omits executing "mov %2, %%ax" at the top of the loop

when "add %1, %%ax" uncommented.

Anyone to doublecheck or comment ?

#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;
}

Follows the assembly generated

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

Thanks to Jester the solution :

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

解决方案

GCC inline assembly is advanced programming, with a lot of pitfalls. Make sure you actually need it, and can't replace it with standalone assembly module, or C code using intrinsics. or vector support.

If you insist on inline assembly, you should be prepared to at least look at the generated assembly code and try to figure out any mistakes from there. Obviously the compiler does not omit anything that you write into the asm block, it just substitutes the arguments. If you look at the generated code, you might see something like this:

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

Apparently the compiler picked dx for both argument 0 and 1. It is allowed to do that, because by default it assumes that the input arguments are consumed before any outputs are written. To signal that this is not the case, you must use an early clobber modifier for your output operand, so it would look like "=&r".

PS: Even when inline assembly seems to work, it may have hidden problems that will bite you another day, when the compiler happens to make other choices. You should really avoid it.

这篇关于意外的GCC内联汇编行为(重挫变量覆盖)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆