我正在尝试在 x86 程序集中进行相对跳转,但是我无法让它工作。似乎由于某种原因,我的跳跃不断被重写为绝对跳跃或其他东西。
我想做的一个简单的示例程序是这样的:
.global main
main:
jmp 0x4
ret
由于 jmp 指令有 4 个字节长,并且相对跳转是从跳转地址 + 1 开始的偏移,因此这应该是一个奇特的无操作。但是,编译并运行此代码将导致分段错误。
对我来说真正的困惑是,将其编译到对象级别,然后反汇编对象文件表明汇编器看起来正确地执行了相对跳转,但在文件编译后链接器将其更改为另一种类型的跳转。
例如,如果上述代码位于名为 asmtest.s 的文件中:
$gcc -c asmtest.s
$objdump -D asmtest.o
... Some info from objdump
00000000 <main>:
0: e9 00 00 00 00 jmp 5 <main+0x5>
5: c3 ret
这看起来汇编器正确地进行了相对跳转,尽管 jmp 指令填充了 0 值得怀疑。
然后我使用 gcc 链接它然后反汇编它并得到这个:
$gcc -o asmtest asmtest.o
$objdump -d asmtest
...Extra info and other disassembled functions
08048394 <main>:
8048394: e9 6b 7c fb f7 jmp 4 <_init-0x8048274>
8048399: c3 ret
在我看来,链接器重写了 jmp 语句,或者将 5 替换为另一个地址。
所以我的问题归结为,我做错了什么?
我是否错误地指定了偏移量?我是否误解了相对跳转的工作原理? gcc 是否试图确保我不会在代码中做危险的事情?