2015-04-20 3 views
1

Этот простой привет мир:Objdump привет мир инструкции вызова

#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 $0xc,%esp 
    804842f:  68 f0 84 04 08   push $0x80484f0 
 8048434:  e8 b7 fe ff ff   call 80482f0 
    8048439:  83 c4 10    add $0x10,%esp 
    /helloworld.c:4 
    804843c:  83 ec 0c    sub $0xc,%esp 
    804843f:  68 f0 84 04 08   push $0x80484f0 
 8048444:  e8 a7 fe ff ff   call 80482f0 
    8048449:  83 c4 10    add $0x10,%esp 
  • Почему же вызов ставит имеют разные шестнадцатеричные коды (b7 vs a7)?
  • e8 является частью вызова, но как b7 Fe и далее и далее переведены на 80482f0?

ответ

1

call rel32 инструкция: Вызов рядом, смещение по отношению к следующей инструкции

Опкод для этой команды E8, после чего относительного смещения, которое вычисляется по следующему уравнению: destination address - address of next instruction.

В этом случае относительное смещение первого вызова составляет 80482f0 - 8048439 = FFFFFEB7, а относительное смещение второго вызова - 80482f0 - 8048449 = FFFFFEA7.

1

Код операции E8 относится к инструкции CALL, адрес которой относится к адресу самой команды CALL. Он использует PC relative addressing. Таким образом, то, что вы видите как адрес функции, фактически является смещением от адреса следующей инструкции до адреса начала функции printf.

К слову, Intel использует мало endian, поэтому эти смещения должны считываться как подписанные 32-разрядные целые числа FFFFFEB7 и FFFEA7 соответственно. Это означает, что функция printf расположена по нижнему адресу относительно вашей основной программы.

Вы можете видеть также, что отличие от этих двух смещений разницы в байтах от одной CALL инструкции к другой, так как второй CALL будет дальше от начала printf, чем первый.

0x8048444 - 0x8048434 = 16 (decimal) 

0xFFFFFEB7 - 0xFFFFFEA7 = 16 (decimal)