我正在使用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”应该被保留?
答案 0 :(得分:2)
有两种方式:
解决它的最佳方法是使用gcc程序集模板 能力。然后你可以告诉编译器你在做什么 寄存器分配器不会使用您的寄存器 其他
快速解决方法是使用“asm volatile”而不是“asm”,这样gcc就不会重新安排 该块内的任何指令。你还是要告诉海湾合作委员会 您正在使用该寄存器,因此它不会存储任何内容 在那里。你还应该在clobber列表中列出“memory”,所以gcc 知道它不能信任它之前可能加载的值 码块。
asm volatile( “代码在这里” :::“eax”,“esp”,“memory” );
答案 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
,它将会造成严重破坏。