一、环境介绍
本系列笔记的所有代码均基于 ubuntu22 5.19.0-38-generic + Intel x86_64 环境验证。
二、C码编译为汇编
1、源码
int main(int argc, char *argv[])
{
write(1, "Hello World\n", 13);
return 0;
}
2、编译
1)只带-S参数:gcc -S hello.c: 会产生很多当前不关注的信息,导致理解困难,放弃。
2)关闭一些默认的选项后编译运行:
$ gcc -fno-stack-protector -fomit-frame-pointer -fno-asynchronous-unwind-tables -fcf-protection=none -S hello.c
$ gcc hello.s
$ ./a.out
Hello World
编译选项解释:
- -fno-stack-protector:去掉 stack 保护,stack protector 用于检查 stack 是否被踩。
- -fomit-frame-pointer:不用 fp 寄存器 rbp/ebp,直接用 stack 寄存器 rsp/esp 就好了。
- -fno-asynchronous-unwind-tables:消除 .eh_frame section等不关注的信息。
- -fcf-protection=none: 消除 endbr64 指令和其他一些不关注的信息。
另外: -mmanual-endbr 选项仅消除 endbr64 指令。
三、编译输出的汇编代码
1、原始的hello.s
.file "hello.c"
.text
.section .rodata
.LC0:
.string "Hello World\n"
.text
.globl main
.type main, @function
main:
subq $24, %rsp
movl %edi, 12(%rsp)
movq %rsi, (%rsp)
movl $13, %edx
leaq .LC0(%rip), %rax
movq %rax, %rsi
movl $1, %edi
movl $0, %eax
call write@PLT
movl $0, %eax
addq $24, %rsp
ret
.size main, .-main
.ident "GCC: (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0"
.section .note.GNU-stack,"",@progbits
2、手动删除不关注的代码后的hello.s
将.LC0 修改为msg
.section .rodata
msg:
.string "Hello World\n"
.text
.globl main
main:
subq $24, %rsp
movl %edi, 12(%rsp)
movq %rsi, (%rsp)
movl $13, %edx
leaq msg(%rip), %rax
movq %rax, %rsi
movl $1, %edi
movl $0, %eax
call write@PLT
movl $0, %eax
addq $24, %rsp
ret