操作数生成的x86-64 AMD上的CALL指令

时间:2022-02-04 02:55:43

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 Rs instead of Es 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 Rs instead of Es in their names, and the addresses would be much longer).

请注意,所有这些数学都是32位。你在这里没有做任何64位操作(或者你的寄存器在名字中会有R而不是Es,地址会更长)。