gcc删除内联汇编代码 [英] gcc removes inline assembler code

查看:149
本文介绍了gcc删除内联汇编代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


$ b

test.c



<$> gcc 4.6.2删除了它认为未从函数中使用的代码。 p $ p> int main(void){
goto exit;
处理程序:
__asm__ __volatile __(jmp 0x0);
exit:
return 0;

$ / code>



反汇编 main()

  0x08048404< + 0> ;: push ebp 
0x08048405< + 1> ;: mov ebp,esp
0x08048407< + 3> ;: nop#< - 这是我jmp的剩余部分。
0x08048408< + 4>:mov eax,0x0
0x0804840d< + 9> ;: pop ebp
0x0804840e< + 10> ;: ret



编译器选项



未启用优化,仅 gcc -m32 -o test test.c -m32 因为我在64位计算机上)。



如何停止这种行为?



编辑:最好使用编译器选项,而不是修改代码。 p>

解决方案

更新2012/6/18

想一想,可以将 goto exit 放入一个asm块中,这意味着只需要更改一行代码:

  int main(void){
__asm__(jmp exit);

处理程序:
__asm__ __volatile __(jmp $ 0x0);
exit:
return 0;



$ b

这比我下面的其他解决方案要干净得多(可能比@ ugoren's也是当前的)。




这很好笑,但它似乎起作用:隐藏处理程序,从来没有在正常条件下遵循,但通过阻止编译器能够使用某些内联汇编程序正确地进行分析来阻止它被消除。

  int main(void){
int x = 0;
__asm__ __volatile__(:= r(x));
//编译器不知道x的值是多少,但它总是为0

if(x){
handler:
__asm__ __volatile__( jmp $ 0x0);
}

返回0;

$ / code>

即使使用 -O3 jmp 被保留:

  testl%eax,%eax 
je .L2
.L3:
jmp $ 0x0
.L2:
xorl%eax,%eax
ret

(这看起来真的很糟糕,所以我希望有更好的方法来做到这一点。 只需在 x volatile / a / 11105198/1256624>工作,因此不需要执行内联asm欺骗。)


It seems like gcc 4.6.2 removes code it considers unused from functions.

test.c

int main(void) {
  goto exit;
  handler:
    __asm__ __volatile__("jmp 0x0");
  exit:
  return 0;
}

Disassembly of main()

   0x08048404 <+0>:     push   ebp
   0x08048405 <+1>:     mov    ebp,esp
   0x08048407 <+3>:     nop    # <-- This is all whats left of my jmp.
   0x08048408 <+4>:     mov    eax,0x0
   0x0804840d <+9>:     pop    ebp
   0x0804840e <+10>:    ret

Compiler options

No optimizations enabled, just gcc -m32 -o test test.c (-m32 because I'm on a 64 bit machine).

How can I stop this behavior?

Edit: Preferably by using compiler options, not by modifing the code.

解决方案

Update 2012/6/18

Just thinking about it, one can put the goto exit in an asm block, which means that only 1 line of code needs to change:

int main(void) {
  __asm__ ("jmp exit");

  handler:
    __asm__ __volatile__("jmp $0x0");
  exit:
  return 0;
}

That is significantly cleaner than my other solution below (and possibly nicer than @ugoren's current one too).


This is pretty hacky, but it seems to work: hide the handler in a conditional that can never be followed under normal conditions, but stop it from being eliminated by stopping the compiler from being able to do its analysis properly with some inline assembler.

int main (void) {
  int x = 0;
  __asm__ __volatile__ ("" : "=r"(x));
  // compiler can't tell what the value of x is now, but it's always 0

  if (x) {
handler:
    __asm__ __volatile__ ("jmp $0x0");
  }

  return 0;
}

Even with -O3 the jmp is preserved:

    testl   %eax, %eax   
    je      .L2     
.L3:
    jmp $0x0
.L2:
    xorl    %eax, %eax 
    ret

(This seems really dodgy, so I hope there is a better way to do this. edit just putting a volatile in front of x works so one doesn't need to do the inline asm trickery.)

这篇关于gcc删除内联汇编代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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