1)
C代码,经典中的经典
#include <stdio.h>
void main()
{
printf("Hello world 123\n");
}
2)生成汇编
gcc -S -O0 b4.hello.c
3)原始的
.file "b4.hello.c"
.text
.section .rodata
.LC0:
.string "Hello world 123"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
leaq .LC0(%rip), %rdi
call puts@PLT
nop
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0"
.section .note.GNU-stack,"",@progbits
4)精简后
.LC0: # 下面4句不能删掉
.string "Hello world 123"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp # push ax 由一下两步完成: 1、SP=SP-2。2、将ax中的内容送入SS:SP指向的内存单元
# 这里可能是rsp。rsp在变
.cfi_def_cfa_offset 16 # 此处距离CFA地址为16字节,值随便改也没有问题。
.cfi_offset 6, -16 #
movq %rsp, %rbp #
.cfi_def_cfa_register 6
leaq .LC0(%rip), %rdi #把 rip偏移.LC0的地址给rdi? 可能跟后面的call对应起来的。
call puts@PLT # 打印,一个参数。
nop # 为什么要插个空转指令?
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
5) gcc -S -O3 b4.hello.c
得到的代码确实简单一些。
.file "b4.hello.c"
.text
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "Hello world 123"
.section .text.startup,"ax",@progbits
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB23:
.cfi_startproc
leaq .LC0(%rip), %rdi #直接打印,确实那push, pop没有什么必要。
jmp puts@PLT
.cfi_endproc
.LFE23:
.size main, .-main
.ident "GCC: (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0"
.section .note.GNU-stack,"",@progbits