Ian Rehwinkel
Ian Rehwinkel

Reputation: 2615

I believe GCC is producing incorrect machine code

I am trying to compile this dead simple program:

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

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

with this command: gcc -c -nostdinc -m32 -masm=intel main.c -O0

The file produced (main.o) has the following object dump:

$ 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 

If I understand correctly, this line 27: e8 fc ff ff ff call 28 <main+0x12> represents the call to print. However, the offset given is -4, which results in jumping to address 28. But there isn't even an instruction at that offset. The code does run however. But I have the feeling this machine code isn't quite right. (Also, why is there a call instruction in the print function, if the print function doesn't even call anything?)

Upvotes: 0

Views: 84

Answers (1)

emacs drives me nuts
emacs drives me nuts

Reputation: 3898

You compiled with -c, thus the output is an object file. It still contains placeholders for symbols and such that will be resolved / patched by the linker. As mentioned, use objdump with flag -r added which will show symbol name for the reloc(s). Before linking, the bits in the opcode are 0, thus the call target points to the address as shown by objdump.

Upvotes: 1

Related Questions