如何在构建intel样式的内联汇编代码时使gcc编译器保留寄存器?

时间:2012-04-24 10:22:29

标签: debugging gcc assembly xcode4 inline-assembly

我正在使用Xcode 4上的gcc编译器构建一些intel样式的内联汇编代码。 下面列出了内联汇编代码的一部分:

_asm
{   
    mov eax, esp
    sub esp, 116
    and esp, ~15
    mov [esp+112], eax       
}

在发货模式下,GCC将以上4行asm代码编译为:

mov    %esp,%eax
sub    $0x74,%esp
and    $0xfffffff0,%esp
mov    %eax,0x70(%esp)

这正是我想要的。 但是,在调试模式下,GCC会将该代码编译为

mov    %esp,%eax
mov    %eax,%esp
mov    %esp,%eax
mov    %eax,-0x28(%ebp)
mov    %esp,%eax
mov    %eax,%esp
sub    $0x74,%esp
mov    %esp,%eax
mov    %eax,-0x24(%ebp)
mov    %esp,%eax
mov    %eax,%esp
**and    $0xfffffff0,%esp**         
**mov    %esp,%eax**        **//changing the value of “eax”**
mov    %eax,-0x24(%ebp)
mov    %esp,%ecx
mov    %ecx,%esp
**mov    %eax,0x70(%esp)**  **//store a “dirty” value to address 0x70(%esp), which is not we want**

解决上述问题的一种方法是使用AT& T样式指令重写内联asm代码,并将寄存器添加到破坏列表中。但这种方式将是一项非常耗时的工作,因为重写的代码是如此......很长。

还有其他有效方法可以解决问题吗?为了使gcc编译器知道寄存器“eax”应该被保留?

2 个答案:

答案 0 :(得分:2)

有两种方式:

  1. 解决它的最佳方法是使用gcc程序集模板 能力。然后你可以告诉编译器你在做什么 寄存器分配器不会使用您的寄存器 其他

  2. 快速解决方法是使用“asm volatile”而不是“asm”,这样gcc就不会重新安排 该块内的任何指令。你还是要告诉海湾合作委员会 您正在使用该寄存器,因此它不会存储任何内容 在那里。你还应该在clobber列表中列出“memory”,所以gcc 知道它不能信任它之前可能加载的值 码块。

    asm volatile(   “代码在这里”   :::“eax”,“esp”,“memory” );

  3. 顺便说一下:你的代码正在做一些“糟糕的事情”,比如移动esp,这可能会引起麻烦,除非你确切知道你在做什么。

答案 1 :(得分:-2)

intel-style块解决问题后的空asm块,如下所示:

__asm volatile {   
    mov eax, esp
    sub esp, 116
    and esp, ~15
    mov [esp+112], eax       
};
__asm__ __volatile__ ("":::"eax", "memory");

但是,如果你不恢复%esp,它将会造成严重破坏。