我正在尝试研究通过汇编中的堆栈将参数传递给函数。我使用的是 Fedora 20,一个 64 位系统。
当我尝试以下代码时:
pushl %ebp
popl %ebp
我收到错误:
错误:‘push’的指令后缀无效
我将如何克服这个错误?
我使用以下方法编译它:
as -ggstabs -o Function_Stack.o Function_Stack.c
您收到的错误来自一个非常简单的事实:32 位模式下的
push
指令接受 16 位和 32 位立即数作为参数。但是,64 位模式下使用的 push
指令仅接受 16 位和 64 位立即数。由于您显然将代码编译为 64 位,因此汇编器会抛出错误,因为它不可能对此类指令进行编码。另外,请记住,您可以通过在 l
指令中添加 push
后缀来强制操作数大小。我刚刚在这里写的所有内容与 pop
完全相同,只是它接受寄存器/内存,而不是立即数。
但是,您还需要记住 32 位和 64 位 Linux 系统之间 ABI 的差异。 ABI 指定了参数如何传递给函数以及如何从用户模式应用程序调用内核等内容。您的代码显然是为 32 位模式编写的,看看它如何使用堆栈来传递参数以及(非常)过时的
int $0x80
调用系统调用的方式。要了解 64 位 ABI,请参阅此文档。
或者,您可以选择在 64 位系统上编译 32 位代码。如果您在 64 位系统上安装了必要的 32 位运行时库,这样的可执行文件就可以工作。大多数发行版允许您以不同的方式做到这一点。您的编译器
as
具有用于发出 32 位代码的 --32
开关。