首页 > 解决方案 > 间接/直接调用指令在内存中的布局如何?

问题描述

我正在将间接调用指令与直接调用指令进行比较,并且我想知道它们在内存中的布局(尤其是在 x86 平台中)。

非常感谢。

标签: assemblyx86callinstructionsmachine-code

解决方案


直接调用看起来像是对函数地址的调用(地址在这里的代码部分中硬写在相对地址 ff ff ff b5 表示 -46 [函数实际上位于调用指令之前的 0x46 字节])

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

虽然间接调用看起来像调用 eax(地址在寄存器中:这里是 rax)

 6e4:   ff d0                   callq  *%rax


一个例子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;
}

编译并执行:gcc main.c -o main && ./main
反汇编:objdump -d main

这是反汇编的操作码

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   

推荐阅读