以下是示例程序的objdump的输出,
080483b4 <display>:
80483b4: 55 push %ebp
80483b5: 89 e5 mov %esp,%ebp
80483b7: 83 ec 18 sub $0x18,%esp
80483ba: 8b 45 0c mov 0xc(%ebp),%eax
80483bd: 89 44 24 04 mov %eax,0x4(%esp)
80483c1: 8d 45 fe lea 0xfffffffe(%ebp),%eax
80483c4: 89 04 24 mov %eax,(%esp)
80483c7: e8 ec fe ff ff call 80482b8 <strcpy@plt>
80483cc: 8b 45 08 mov 0x8(%ebp),%eax
80483cf: 89 44 24 04 mov %eax,0x4(%esp)
80483d3: c7 04 24 f0 84 04 08 movl $0x80484f0,(%esp)
80483da: e8 e9 fe ff ff call 80482c8 <printf@plt>
80483df: c9 leave
80483e0: c3 ret
080483e1 <main>:
80483e1: 8d 4c 24 04 lea 0x4(%esp),%ecx
80483e5: 83 e4 f0 and $0xfffffff0,%esp
80483e8: ff 71 fc pushl 0xfffffffc(%ecx)
80483eb: 55 push %ebp
80483ec: 89 e5 mov %esp,%ebp
80483ee: 51 push %ecx
80483ef: 83 ec 24 sub $0x24,%esp
80483f2: c7 44 24 04 f3 84 04 movl $0x80484f3,0x4(%esp)
80483f9: 08
80483fa: c7 04 24 0a 00 00 00 movl $0xa,(%esp)
8048401: e8 ae ff ff ff call 80483b4 <display>
8048406: b8 00 00 00 00 mov $0x0,%eax
804840b: 83 c4 24 add $0x24,%esp
804840e: 59 pop %ecx
804840f: 5d pop %ebp
8048410: 8d 61 fc lea 0xfffffffc(%ecx),%esp
我需要理解的是,主要是我们在地址--8048401看到以下内容,调用80483b4,但机器代码是 - e8 ae ff ff ff。我看到CALL指令是E8,但是函数80483b4的地址如何被解码为FFFFFFAE?我在谷歌做了很多搜索,但它没有返回任何东西。有人可以解释一下吗?
答案 0 :(得分:10)
E8是“Call Relative”的操作数,意味着通过将操作数添加到下一条指令的地址来计算目标地址。操作数为0xFFFFFFAE,为负0x52。 0x808406 - 0x52是0x80483b4。
大多数反汇编程序都有助于计算实际的目标地址,而不仅仅是给出操作数中的相对地址。
答案 1 :(得分:6)
有趣的问题。我查看了Intel's documentation,E8
操作码是CALL rel16/32
。 0xffffffae实际上是一个32位二进制补码有符号整数,等于-82十进制;它是紧跟在操作码及其操作数之后的字节的相对地址。
如果你做数学计算,你可以看到它结帐:
0x8048406 - 82 = 0x80483b4
这将指令指针放在display
函数的开头。
答案 2 :(得分:3)
近呼叫通常是IP相关的 - 意思是,“地址”实际上是指令指针的偏移量。在这种情况下,EIP指向下一条指令(因此其值为8048406
)。将ffffffae
(或-00000052
加成两个补码)添加到其中,即可获得80483b4
。
请注意,所有这些数学都是32位的。你在这里没有做任何64位操作(或者你的寄存器名称中会有R
而不是E
,并且地址会更长。)