Я считаю, что G CC производит неправильный машинный код - PullRequest
0 голосов
/ 22 апреля 2020

Я пытаюсь скомпилировать эту мертвую простую программу:

int print(int x, int y)
{
    return x * y;
}

int main()
{
    return print(8, 7);
}

с помощью этой команды: gcc -c -nostdinc -m32 -masm=intel main.c -O0

Полученный файл (main.o) имеет следующий объектный дамп:

$ objdump -d main.o                             

main.o:     file format elf32-i386


Disassembly of section .text:

00000000 <print>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   e8 fc ff ff ff          call   4 <print+0x4>
   8:   05 01 00 00 00          add    $0x1,%eax
   d:   8b 45 08                mov    0x8(%ebp),%eax
  10:   0f af 45 0c             imul   0xc(%ebp),%eax
  14:   5d                      pop    %ebp
  15:   c3                      ret    

00000016 <main>:
  16:   55                      push   %ebp
  17:   89 e5                   mov    %esp,%ebp
  19:   e8 fc ff ff ff          call   1a <main+0x4>
  1e:   05 01 00 00 00          add    $0x1,%eax
  23:   6a 07                   push   $0x7
  25:   6a 08                   push   $0x8
  27:   e8 fc ff ff ff          call   28 <main+0x12>
  2c:   83 c4 08                add    $0x8,%esp
  2f:   c9                      leave  
  30:   c3                      ret    

Disassembly of section .text.__x86.get_pc_thunk.ax:

00000000 <__x86.get_pc_thunk.ax>:
   0:   8b 04 24                mov    (%esp),%eax
   3:   c3                      ret 

Если я правильно понимаю, эта строка 27: e8 fc ff ff ff call 28 <main+0x12> представляет вызов print. Однако заданное смещение равно -4, что приводит к переходу на адрес 28. Но даже с этим смещением нет инструкции. Код работает, однако. Но я чувствую, что этот машинный код не совсем правильный. (Кроме того, почему в функции печати есть инструкция call, если функция печати вообще ничего не вызывает?)

1 Ответ

1 голос
/ 26 апреля 2020

Вы скомпилировали с -c, поэтому выходной файл является объектным файлом. Он по-прежнему содержит заполнители для символов и такие, которые будут разрешены / исправлены компоновщиком. Как уже упоминалось, используйте objdump с добавленным флагом -r, который покажет имя символа для relo c (s). Перед связыванием биты в коде операции равны 0, поэтому цель вызова указывает на адрес, как показано в objdump.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...