我正在为一个类编写一个编译器,并且我坚持使用 GNU 的语法来进行间接调用。考虑这个简单的程序:
.text
.globl main
main:
movl func, %eax
call *%eax
ret
func:
movl $42, %eax
ret
编译gcc -m32 -O0
并运行生成的程序会给我一个分段错误。谁能告诉我如何正确拨打电话?
谢谢。
文森特。
我正在为一个类编写一个编译器,并且我坚持使用 GNU 的语法来进行间接调用。考虑这个简单的程序:
.text
.globl main
main:
movl func, %eax
call *%eax
ret
func:
movl $42, %eax
ret
编译gcc -m32 -O0
并运行生成的程序会给我一个分段错误。谁能告诉我如何正确拨打电话?
谢谢。
文森特。
call
指令本身实际上是好的。:)
您的问题是您似乎忘记了 AT&T 语法的工作原理。您在这里所做的movl func, %eax
是将标签地址中的双字复制func
到eax
寄存器中。本质上,eax
以函数的前 4 个字节的实际代码结束。
AT&T 中的立即操作数以 . 为前缀$
。作为编译时常量的func
标签的值可以用作立即数,这就是您在这种情况下想要的。因此,替换movl func, %eax
为movl $func, %eax
,你会没事的。:)
在这里使用lea
是多余的。当然,它会起作用,但由于func
它是一个编译时常量,因此将它简单地放在代码中而不是在运行时找出它会更有效。
我想我明白了;使用lea
而不是movl
解决问题;我想 lea 进行虚拟地址转换。