Каковы значения параметров команды callq? - PullRequest
2 голосов
/ 14 мая 2019

Я знаю, что делает инструкция callq; это описано в этом ответе . Инструкция должна иметь один параметр, который должен быть адресом вызываемой функции.

Однако при разборке объектного файла я вижу следующую строку, показывающую инструкцию callq с двумя значениями вместо одного параметра:

  1e:   e8 00 00 00 00          callq  23 <main+0x19>

Я предполагаю, что 23 - это адрес возврата, а <main+0x19> - это адрес вызываемой функции. Однако вызываемая функция не находится по адресу main+0x19.

Что означают два значения 23 и main+0x19, показанные в разборке инструкции callq?


Оригинальный код C:

#include <stdio.h>

void fun(int a)
{
}

int main()
{
    int a = 1234;
    fun(a);
}

objdump -D main.o main.asm Разъединенный код:

0000000000000000 <fun>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   89 7d fc                mov    %edi,-0x4(%rbp)
   7:   90                      nop
   8:   5d                      pop    %rbp
   9:   c3                      retq   

000000000000000a <main>:
   a:   55                      push   %rbp
   b:   48 89 e5                mov    %rsp,%rbp
   e:   48 83 ec 10             sub    $0x10,%rsp
  12:   c7 45 fc 03 00 00 00    movl   $0x3,-0x4(%rbp)
  19:   8b 45 fc                mov    -0x4(%rbp),%eax
  1c:   89 c7                   mov    %eax,%edi
  1e:   e8 00 00 00 00          callq  23 <main+0x19>
  23:   b8 00 00 00 00          mov    $0x0,%eax
  28:   c9                      leaveq 
  29:   c3                      retq   

1 Ответ

3 голосов
/ 14 мая 2019

Инструкция callq имеет только один операнд, а не два, как подразумевается в вопросе.Дизассемблер отображает его в двух формах: в виде адреса и в виде символа + смещение.

Вы просматриваете разборку несвязанного объектного файла.Поскольку дизассемблированный файл не связан, указанный адрес назначения не является адресом fun.Ассемблер помещает 0 в поле операнда инструкции и создает запись перемещения для компоновщика, чтобы заполнить смещение до конечного адреса получателя.

Операнд инструкции вызова смещение относительно адреса следующей инструкции после вызова.Таким образом, значение 0 в поле операнда заставляет дизассемблер отображать адрес следующей инструкции в качестве пункта назначения вызова.В показанной разборке это адрес 23.

Если вы сделаете fun статической функцией, ассемблер может заполнить истинное смещение функции, так как это не потребует перемещения, и вы увидитеэто в разборке.(Это может зависеть от того, какие именно инструменты и опции вы используете.)

Если вы разберете исполняемый файл связанный , дизассемблер покажет истинный адрес назначения вызова.

...