[内存结构]
C程序通过编译-汇编-连接,最后到可执行文件。载入内存有这几个部分:
text:正文段,存放的是可执行的机器码段
data:存放初始化之后的全局变量和静态变量
bbs:存放未初始化的静态变量和全局变量
heap:堆,由程序员自己分配和释放,程序结束时,操作系统也会释放。
stack: 栈,编译器自动分配,存放函数的参数,局部变量
下图是典型的内存布局图
#include <stdio.h> #include <stdlib.h> void foo(int x){printf("hello");} typedef void(*FunCall)(int); typedef struct{ FunCall b; char c; int a; }AA; int main(){ AA aa; aa.c = ‘s‘; aa.a = 7; aa.b = foo; (*(aa.b))(aa.a); return 0; }
这是一个很简单的程序, 使用GCC编译选项编译成AT&T语法的汇编语言
gcc -S test1.c
下面来分析汇编代码
1 .file "test1.c" 2 .section .rodata 3 .LC0: 4 .string "hello" 5 .text 6 .globl foo 7 .type foo, @function 8 foo: 9 .LFB0: 10 .cfi_startproc 11 pushq %rbp 12 .cfi_def_cfa_offset 16 13 movq %rsp, %rbp 14 .cfi_offset 6, -16 15 .cfi_def_cfa_register 6 16 subq $16, %rsp 17 movl %edi, -4(%rbp) 18 movl $.LC0, %eax 19 movq %rax, %rdi 20 movl $0, %eax 21 call printf 22 leave 23 .cfi_def_cfa 7, 8 24 ret 25 .cfi_endproc 26 .LFE0: 27 .size foo, .-foo 28 .globl main 29 .type main, @function 30 main: 31 .LFB1: 32 .cfi_startproc 33 pushq %rbp 34 .cfi_def_cfa_offset 16 35 movq %rsp, %rbp 36 .cfi_offset 6, -16 37 .cfi_def_cfa_register 6 38 subq $16, %rsp 39 movb $115, -8(%rbp) 40 movl $7, -4(%rbp) 41 movq $foo, -16(%rbp) 42 movq -16(%rbp), %rdx 43 movl -4(%rbp), %eax 44 movl %eax, %edi 45 call *%rdx 46 movl $0, %eax 47 leave 48 .cfi_def_cfa 7, 8 49 ret 50 .cfi_endproc 51 .LFE1: 52 .size main, .-main 53 .ident "GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2" 54 .section .note.GNU-stack,"",@progbits
以点开头的是汇编指示。
指令介绍
寄存器介绍
函数调用
汇编生成
gcc -g -c test.c objdump -d -M intel -S test.o