0

I'm comparing indirect call instruction against direct call instruction, and I want to know the layout( of them in memory, espically in x86 platform.

Many thanks.

JiaHao Xu
  • 2,452
  • 16
  • 31
  • 1
    http://felixcloutier.com/x86/CALL.html documents the machine-code encodings. `call rel32` vs. `call modr/m` – Peter Cordes May 12 '18 at 05:11
  • installing assembler is like `sudo apt-get install nasm` in modern OS... or you can even use online one https://defuse.ca/online-x86-assembler.htm ... plus documentation. Makes me wonder what you are "comparing" if you didn't bother to get even basic data like encoding of them, not even mentioning things like performance which is lot more harder to evaluate correctly. – Ped7g May 12 '18 at 06:14
  • How to say this... I learnt sth like human-readable assembly code, but never touches a bit about encoding... – JiaHao Xu May 12 '18 at 06:25
  • hm, that's fine, almost every assembler has "listing" option, where you can verify how your source did assemble to machine code (before linking). For fully linked machine code it is usually easiest to breakpoint in debugger and check the disassembly there, but in my experience the listing file is often enough to verify some assumptions and find eventually some problems or improvements in data layout/etc. And of course when I'm size-coding things like 256B intros, I spend lot of time in the listing to figure out which parts of code are big and thinking how to rewrite them for smaller code. – Ped7g May 12 '18 at 07:31
  • I have no idea what “layout of a call” is supposed to mean. – fuz May 12 '18 at 11:52
  • @JiaHaoXu: use a disassembler that prints the machine code, like `objdump -drwC -Mintel my_program` – Peter Cordes May 12 '18 at 14:54

1 Answers1

1

A direct call looks like a call to the adress of the fucntion (the address is hardwritten in the code section here at the relative address ff ff ff b5 means -46 [the function actually is located 0x46 bytes before the call instruction])

 6d0:   e8 b5 ff ff ff          callq  68a <subroutine>

While an indirect call looks like a call eax (the address is in a register : here rax)

 6e4:   ff d0                   callq  *%rax


An example main.c

#include <stdio.h>

typedef int (*func_t)(void);

int subroutine(){
    printf("  I am the subroutine\n");
    return 0;
}

int main(int argc, char *argv[])
{
    printf("--> Start %s\n", argv[0]);

    // Direct call
    subroutine();

    // Indirect call
    func_t f_sub = &subroutine;
    f_sub();

    return 0;
}

Compile and execute : gcc main.c -o main && ./main
Disassemble : objdump -d main

And here is the disassembled opcodes

00000000000006a1 <main>:
 6a1:   55                      push   %rbp
 6a2:   48 89 e5                mov    %rsp,%rbp
 6a5:   48 83 ec 20             sub    $0x20,%rsp
 6a9:   89 7d ec                mov    %edi,-0x14(%rbp)
 6ac:   48 89 75 e0             mov    %rsi,-0x20(%rbp)
 6b0:   48 8b 45 e0             mov    -0x20(%rbp),%rax
 6b4:   48 8b 00                mov    (%rax),%rax
 6b7:   48 89 c6                mov    %rax,%rsi
 6ba:   48 8d 3d e9 00 00 00    lea    0xe9(%rip),%rdi        # 7aa <_IO_stdin_used+0x1a>
 6c1:   b8 00 00 00 00          mov    $0x0,%eax
 6c6:   e8 95 fe ff ff          callq  560 <printf@plt>
 6cb:   b8 00 00 00 00          mov    $0x0,%eax
 6d0:   e8 b5 ff ff ff          callq  68a <subroutine>
 6d5:   48 8d 05 ae ff ff ff    lea    -0x52(%rip),%rax        # 68a <subroutine>
 6dc:   48 89 45 f8             mov    %rax,-0x8(%rbp)
 6e0:   48 8b 45 f8             mov    -0x8(%rbp),%rax
 6e4:   ff d0                   callq  *%rax
 6e6:   b8 00 00 00 00          mov    $0x0,%eax
 6eb:   c9                      leaveq 
 6ec:   c3                      retq   
Tinmarino
  • 3,693
  • 24
  • 33