objdump hello world调用说明

Objdump hello world call instructions

这个简单的问候世界:

#include <stdio.h>
int main(void) {
  printf("Hello, world!\n");
  printf("Hello, world!\n");
  return 0;
}

在 objdump 中给出以下程序集:

    /helloworld.c:3
     804842c:       83 ec 0c                sub    [=11=]xc,%esp
     804842f:       68 f0 84 04 08          push   [=11=]x80484f0
     8048434:       e8 b7 fe ff ff          call   80482f0 
     8048439:       83 c4 10                add    [=11=]x10,%esp
    /helloworld.c:4
     804843c:       83 ec 0c                sub    [=11=]xc,%esp
     804843f:       68 f0 84 04 08          push   [=11=]x80484f0
     8048444:       e8 a7 fe ff ff          call   80482f0 
     8048449:       83 c4 10                add    [=11=]x10,%esp

call rel32指令:调用near,相对于下一条指令的位移

此指令的操作码是 E8,后跟通过以下等式计算的相对偏移量:destination address - address of next instruction.

此时第一次调用的相对偏移量为80482f0 - 8048439 = FFFFFEB7,第二次调用的相对偏移量为80482f0 - 8048449 = FFFFFEA7.

E8操作码属于CALL指令,其地址是相对于CALL指令本身的地址。它使用 PC relative addressing。所以,你看到的函数地址实际上是从下一条指令的地址到printf函数开始地址的偏移。

顺便说一句,英特尔使用小端,所以这些偏移量必须分别读取为带符号的 32 位整数 FFFFFEB7FFFEA7。这意味着 printf 函数位于相对于您的主程序的较低地址。

您还可以看到,这两个偏移量的差异是一条 CALL 指令与另一条指令的字节差异,因为第二条 CALL 距离 printf 比第一个.

0x8048444 - 0x8048434 = 16 (decimal)

0xFFFFFEB7 - 0xFFFFFEA7 = 16 (decimal)