汇编语言中 jmp offset <label+offset> 是什么意思?

3

我使用了

objdump -M intel -d test

and

objdump -d test

使用gcc 686-elf交叉编译器反汇编一个非常简单的for循环,我在两种情况下都得到了以下结果:

 d:   eb 11                   jmp    20 <loop+0x20>

完整的转储(INTEL)如下:
00000000 <loop>:
0:   55                      push   ebp
1:   89 e5                   mov    ebp,esp
3:   83 ec 10                sub    esp,0x10
6:   c7 45 fc 00 00 00 00    mov    DWORD PTR [ebp-0x4],0x0
d:   eb 11                   jmp    20 <loop+0x20>
f:   a1 00 00 00 00          mov    eax,ds:0x0
14:   83 c0 01                add    eax,0x1
17:   a3 00 00 00 00          mov    ds:0x0,eax
1c:   83 45 fc 01             add    DWORD PTR [ebp-0x4],0x1
20:   83 7d fc 09             cmp    DWORD PTR [ebp-0x4],0x9
24:   7e e9                   jle    f <loop+0xf>
26:   90                      nop
27:   c9                      leave  
28:   c3                      ret   

如果它从标签为 loop 的位置(0)跳转到偏移量 20,则这是有意义的。

令我困惑的是语法。为什么有两个数字 20?

20 <loop+0x20>

1
请记住,jmp 是相对的,而不是绝对的。因此它是一个偏移量,而不是一个地址。 - Oliver Charlesworth
我会更正它。谢谢。 - Makketronix
2
jmp 20 <loop+0x20> 中,<loop+0x20> 是反汇编器提供的信息输出。在这种情况下,JMP 是相对于 JMP 指令本身的结尾。下一条指令位于 0xf,因此汇编器将相对跳转编码为从跳转结尾开始的 +0x11。0x11+0x0f = 0x20。您可以在操作码输出 eb 11 中看到 11 的相对编码。 - Michael Petch
2
旁注:“完整转储(AT&T)”可能应该改为“完整转储(INTEL)”。 - Michael Petch
1
信息部分<loop+0x20>表示跳转的目标地址是从标签loop(即当前函数的开头)开始的0x20字节(32十进制)。很容易看出,从loop的开头算起的0x20是20: 83 7d fc 09 cmp DWORD PTR [ebp-0x4],0x9(请注意开头的20:)。 - Michael Petch
显示剩余2条评论
1个回答

4

十六进制20是跳转目标地址。loop+0x20本意是有帮助的,但在这种情况下并不是。反汇编器找到了最接近20的符号地址。在这种情况下,它是loop。它重新计算了20作为该标签的偏移量。由于该标签位于地址0,因此简化为0+0x20,即20,与您预期的目标相等。

在其他情况下,这种表示方法更有帮助。例如,如果一个标签a代表一个int数组的基址,则<a+0x20>将指定数组的第32个字节,即a[8]


那么<label+offset>不是x86汇编的有效语法,而只是反汇编器提供给用户阅读的附加信息,我说得对吗? - Shuai
我不确定某个汇编程序是否接受它。但是反汇编程序的输出没有义务成为任何汇编程序的有效输入。由于存在多种语法,因此没有单一的“有效语法”。 - Gene

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接