编辑
2024-01-14
工作知识
0
请注意,本文编写于 509 天前,最后修改于 451 天前,其中某些信息可能已经过时。

目录

从c程序来理解X86汇编
简单的代码
参考链接

从c程序来理解X86汇编

回顾x86汇编

简单的代码

#include <stdio.h> int main() { int a = 5; int b = a + 6; return 0; }

gcc -g -O0 simple.c -o simple gdb ./simple

(gdb) b main Breakpoint 1 at 0x1129: file simple.c, line 3. (gdb) r Starting program: /home/vivien/test/simple Breakpoint 1, main () at simple.c:3 3 { (gdb) n 2 5 int b = a + 6; (gdb) disass Dump of assembler code for function main: 0x0000555555555129 <+0>: endbr64 0x000055555555512d <+4>: push %rbp 0x000055555555512e <+5>: mov %rsp,%rbp 0x0000555555555131 <+8>: movl $0x5,-0x8(%rbp) => 0x0000555555555138 <+15>: mov -0x8(%rbp),%eax 0x000055555555513b <+18>: add $0x6,%eax 0x000055555555513e <+21>: mov %eax,-0x4(%rbp) 0x0000555555555141 <+24>: mov $0x0,%eax 0x0000555555555146 <+29>: pop %rbp 0x0000555555555147 <+30>: retq End of assembler dump.

这里disassemble命令默认以AT&T语法输出汇编指令 AT&T 语法中的指令格式为mnemonic source, destination 立即数为$符号,寄存器为%符号。 %eax是累加器,return的值也会放在这里 %ecx是计数器 %ebx是基地址寄存器 %edx是数据寄存器 %rbp是基指针,指向当前基址指针 %rsp是栈指针,指向当前堆栈指针

push %rbp mov %rsp,%rbp

这里将旧的基址指针压入栈保存备用,并将堆栈指针复制到基址指针上,这样%rbp指向main函数的栈帧底部。

movl $0x5,-0x8(%rbp) mov -0x8(%rbp),%eax add $0x6,%eax mov %eax,-0x4(%rbp)

这里将立即数5存储到 %rbp-8的局部变量中,再将%rbp-8移动到累加器中,然后对%eax自加6,然后将%eax的值存放在%rbp-4的局部变量

mov $0x0,%eax pop %rbp retq

这里将立即数0复制给%eax用作return的返回,并通过pop把旧的基指针从堆栈中取出并存回%rbp中。retq跳转回返回地址 在gdb中打印值来看看。

(gdb) x $rbp - 8 0x7fffffffe4f8: 0x00000005 (gdb) x &a 0x7fffffffe4f8: 0x00000005 (gdb) x &b 0x7fffffffe4fc: 0x0000000b (gdb) x $rbp - 4 0x7fffffffe4fc: 0x0000000b (gdb) x $rbp 0x7fffffffe500: 0x00000000

参考链接

https://www.recurse.com/blog/7-understanding-c-by-learning-assembly?utm_source=wechat_session&utm_medium=social&utm_oi=801824054439985152