Following is the output of objdump of a sample program,
以下是示例程序的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
What i need to understand, is in main we see the following at address - 8048401, call 80483b4 , however the machine code is - e8 ae ff ff ff. I see that CALL instruction is E8 but how is the address of function 80483b4 getting decoded to FFFFFFAE? I did a lot of search in google but it did not return anything. Can Anyone please explain?
我需要了解的是,主要是我们在地址 - 8048401看到以下内容,调用80483b4,但机器代码是 - e8 ae ff ff ff。我看到CALL指令是E8,但是函数80483b4的地址如何被解码为FFFFFFAE?我在谷歌做了很多搜索,但它没有返回任何东西。有人可以解释一下吗?
3 个解决方案
#1
9
E8 is the operand for "Call Relative", meaning the destination address is computed by adding the operand to the address of the next instruction. The operand is 0xFFFFFFAE, which is negative 0x52. 0x808406 - 0x52 is 0x80483b4.
E8是“Call Relative”的操作数,意味着通过将操作数添加到下一条指令的地址来计算目标地址。操作数为0xFFFFFFAE,为负0x52。 0x808406 - 0x52是0x80483b4。
Most disassemblers helpfully calculate the actual target address rather than just give you the relative address in the operand.
大多数反汇编程序有助于计算实际的目标地址,而不仅仅是给出操作数中的相对地址。
Complete info for x86 ISA at: http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-vol-2a-manual.html
有关x86 ISA的完整信息,请访问:http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-vol-2a-manual.html
#2
6
Interesting question. I've had a look at Intel's documentation and the E8
opcode is CALL rel16/32
. 0xffffffae is actually a 32-bit two's complement signed integer equal to -82 decimal; it is a relative address from the byte immediately after the opcode and its operands.
有趣的问题。我查看了英特尔的文档,E8操作码是CALL rel16 / 32。 0xffffffae实际上是一个32位二进制补码有符号整数,等于-82十进制;它是紧跟在操作码及其操作数之后的字节的相对地址。
If you do the math you can see it checks out:
如果你做数学,你可以看到它检查:
0x8048406 - 82 = 0x80483b4
0x8048406 - 82 = 0x80483b4
This puts the instruction pointer at the beginning of the display
function.
这将指令指针放在显示功能的开头。
#3
3
Near calls are typically IP-relative -- meaning, the "address" is actually an offset from the instruction pointer. In such case, EIP points to the next instruction (so its value is 8048406
). Add ffffffae
(or -00000052
in two's complement) to it, and you get 80483b4
.
近调用通常是IP相关的 - 意思是,“地址”实际上是指令指针的偏移量。在这种情况下,EIP指向下一条指令(因此其值为8048406)。添加ffffffae(或两个补码中的-00000052),得到80483b4。
Note that all this math is 32-bit. You're not doing any 64-bit operations here (or your registers would have R
s instead of E
s in their names, and the addresses would be much longer).
请注意,所有这些数学都是32位。你在这里没有做任何64位操作(或者你的寄存器在名字中会有R而不是Es,地址会更长)。
#1
9
E8 is the operand for "Call Relative", meaning the destination address is computed by adding the operand to the address of the next instruction. The operand is 0xFFFFFFAE, which is negative 0x52. 0x808406 - 0x52 is 0x80483b4.
E8是“Call Relative”的操作数,意味着通过将操作数添加到下一条指令的地址来计算目标地址。操作数为0xFFFFFFAE,为负0x52。 0x808406 - 0x52是0x80483b4。
Most disassemblers helpfully calculate the actual target address rather than just give you the relative address in the operand.
大多数反汇编程序有助于计算实际的目标地址,而不仅仅是给出操作数中的相对地址。
Complete info for x86 ISA at: http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-vol-2a-manual.html
有关x86 ISA的完整信息,请访问:http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-vol-2a-manual.html
#2
6
Interesting question. I've had a look at Intel's documentation and the E8
opcode is CALL rel16/32
. 0xffffffae is actually a 32-bit two's complement signed integer equal to -82 decimal; it is a relative address from the byte immediately after the opcode and its operands.
有趣的问题。我查看了英特尔的文档,E8操作码是CALL rel16 / 32。 0xffffffae实际上是一个32位二进制补码有符号整数,等于-82十进制;它是紧跟在操作码及其操作数之后的字节的相对地址。
If you do the math you can see it checks out:
如果你做数学,你可以看到它检查:
0x8048406 - 82 = 0x80483b4
0x8048406 - 82 = 0x80483b4
This puts the instruction pointer at the beginning of the display
function.
这将指令指针放在显示功能的开头。
#3
3
Near calls are typically IP-relative -- meaning, the "address" is actually an offset from the instruction pointer. In such case, EIP points to the next instruction (so its value is 8048406
). Add ffffffae
(or -00000052
in two's complement) to it, and you get 80483b4
.
近调用通常是IP相关的 - 意思是,“地址”实际上是指令指针的偏移量。在这种情况下,EIP指向下一条指令(因此其值为8048406)。添加ffffffae(或两个补码中的-00000052),得到80483b4。
Note that all this math is 32-bit. You're not doing any 64-bit operations here (or your registers would have R
s instead of E
s in their names, and the addresses would be much longer).
请注意,所有这些数学都是32位。你在这里没有做任何64位操作(或者你的寄存器在名字中会有R而不是Es,地址会更长)。