读懂汇编代码
首页 专栏 c 文章详情
0

读懂汇编代码

doujiang24 发布于 3 月 2 日

对于这样一份 C 代码:

int add (int a, int b) {
    return a + b;
}

int main (void) {
    int a = 10;
    int b = 20;
    int c = add(a, b);
    return c;
}

先使用 gcc 编译

$ gcc -g -O0 hello.c -o hello

然后使用 objdump 来查看反汇编
只摘取其中结果中最重要的汇编代码,# 之后的内容为手动加的注释

$ objdump -j .text -d hello

00000000004004ed <add>:

  4004ed:       55                      push   %rbp         # 将 rbp 寄存器的值压入栈
  4004ee:       48 89 e5                mov    %rsp,%rbp    # 将 rsp 寄存器的值 移动到 rbp 寄存器,栈底(rbp)移动到原来的栈顶的位置(rsp)
  4004f1:       89 7d fc                mov    %edi,-0x4(%rbp)  # 将 edi 寄存器的值,移动到 -0x4(相对于 rbp 的地址)
  4004f4:       89 75 f8                mov    %esi,-0x8(%rbp)  # 将 esi 寄存器的值,移动到 -0x8(相对于 rbp 的地址)
  4004f7:       8b 45 f8                mov    -0x8(%rbp),%eax  # 将 -0x8 的值移动到 eax
  4004fa:       8b 55 fc                mov    -0x4(%rbp),%edx  # 将 -0x4 的值移动到 edx
  4004fd:       01 d0                   add    %edx,%eax        # eax += edx
}
  4004ff:       5d                      pop    %rbp             # 从栈顶弹出一个值,放到 rbp 里
  400500:       c3                      retq                    # 从栈顶弹出一个值,放到 rip 里,也就是相当于 pop %rip

0000000000400501 <main>:

  400501:       55                      push   %rbp             # 将 rbp 压入栈
  400502:       48 89 e5                mov    %rsp,%rbp        # 将 rsp 寄存器的值 移动到 rbp 寄存器,栈底(rbp)移动到原来的栈顶的位置(rsp)
  400505:       48 83 ec 10             sub    $0x10,%rsp       # rsp -= 0x10,栈顶向下生长高度 0x10
  400509:       c7 45 fc 0a 00 00 00    movl   $0xa,-0x4(%rbp)  # 将整数 0xa 移动到 -0x4(相对于 rbp)
  400510:       c7 45 f8 14 00 00 00    movl   $0x14,-0x8(%rbp) # 将整数 0x14 移动到 -0x8(相对于 rbp)
  400517:       8b 55 f8                mov    -0x8(%rbp),%edx  # 将 -0x8 移动到 edx
  40051a:       8b 45 fc                mov    -0x4(%rbp),%eax  # 将 -0x4 移动到 eax
  40051d:       89 d6                   mov    %edx,%esi        # esi = edx
  40051f:       89 c7                   mov    %eax,%edi        # edi = eax
  400521:       e8 c7 ff ff ff          callq  4004ed <add>     # 调用函数 add
  400526:       89 45 f4                mov    %eax,-0xc(%rbp)  # 将 eax 移动到 -0xc
  400529:       8b 45 f4                mov    -0xc(%rbp),%eax  # 将 -0xc 移动到 eax
  40052c:       c9                      leaveq                  # 相当于movq %rbp, %rsp + popq %rbp,将 rbp 和 rsp 回退到上一帧
  40052d:       c3                      retq                    # 从栈顶弹出一个值,放到 rip 里,也就是相当于 pop %rip
  40052e:       66 90                   xchg   %ax,%ax          # nop
c
阅读 45 更新于 3 月 2 日
收藏
分享
本作品系原创, 采用《署名-非商业性使用-禁止演绎 4.0 国际》许可协议
avatar
doujiang24

中年程序员

0 声望
0 粉丝
关注作者
0 条评论
得票 时间
提交评论
avatar
doujiang24

中年程序员

0 声望
0 粉丝
关注作者
宣传栏
目录

对于这样一份 C 代码:

int add (int a, int b) {
    return a + b;
}

int main (void) {
    int a = 10;
    int b = 20;
    int c = add(a, b);
    return c;
}

先使用 gcc 编译

$ gcc -g -O0 hello.c -o hello

然后使用 objdump 来查看反汇编
只摘取其中结果中最重要的汇编代码,# 之后的内容为手动加的注释

$ objdump -j .text -d hello

00000000004004ed <add>:

  4004ed:       55                      push   %rbp         # 将 rbp 寄存器的值压入栈
  4004ee:       48 89 e5                mov    %rsp,%rbp    # 将 rsp 寄存器的值 移动到 rbp 寄存器,栈底(rbp)移动到原来的栈顶的位置(rsp)
  4004f1:       89 7d fc                mov    %edi,-0x4(%rbp)  # 将 edi 寄存器的值,移动到 -0x4(相对于 rbp 的地址)
  4004f4:       89 75 f8                mov    %esi,-0x8(%rbp)  # 将 esi 寄存器的值,移动到 -0x8(相对于 rbp 的地址)
  4004f7:       8b 45 f8                mov    -0x8(%rbp),%eax  # 将 -0x8 的值移动到 eax
  4004fa:       8b 55 fc                mov    -0x4(%rbp),%edx  # 将 -0x4 的值移动到 edx
  4004fd:       01 d0                   add    %edx,%eax        # eax += edx
}
  4004ff:       5d                      pop    %rbp             # 从栈顶弹出一个值,放到 rbp 里
  400500:       c3                      retq                    # 从栈顶弹出一个值,放到 rip 里,也就是相当于 pop %rip

0000000000400501 <main>:

  400501:       55                      push   %rbp             # 将 rbp 压入栈
  400502:       48 89 e5                mov    %rsp,%rbp        # 将 rsp 寄存器的值 移动到 rbp 寄存器,栈底(rbp)移动到原来的栈顶的位置(rsp)
  400505:       48 83 ec 10             sub    $0x10,%rsp       # rsp -= 0x10,栈顶向下生长高度 0x10
  400509:       c7 45 fc 0a 00 00 00    movl   $0xa,-0x4(%rbp)  # 将整数 0xa 移动到 -0x4(相对于 rbp)
  400510:       c7 45 f8 14 00 00 00    movl   $0x14,-0x8(%rbp) # 将整数 0x14 移动到 -0x8(相对于 rbp)
  400517:       8b 55 f8                mov    -0x8(%rbp),%edx  # 将 -0x8 移动到 edx
  40051a:       8b 45 fc                mov    -0x4(%rbp),%eax  # 将 -0x4 移动到 eax
  40051d:       89 d6                   mov    %edx,%esi        # esi = edx
  40051f:       89 c7                   mov    %eax,%edi        # edi = eax
  400521:       e8 c7 ff ff ff          callq  4004ed <add>     # 调用函数 add
  400526:       89 45 f4                mov    %eax,-0xc(%rbp)  # 将 eax 移动到 -0xc
  400529:       8b 45 f4                mov    -0xc(%rbp),%eax  # 将 -0xc 移动到 eax
  40052c:       c9                      leaveq                  # 相当于movq %rbp, %rsp + popq %rbp,将 rbp 和 rsp 回退到上一帧
  40052d:       c3                      retq                    # 从栈顶弹出一个值,放到 rip 里,也就是相当于 pop %rip
  40052e:       66 90                   xchg   %ax,%ax          # nop