标签:
long#long + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
C程序代码:
1 int g(int x) 2 { 3 return x + 3; 4 } 5 6 int f(int x) 7 { 8 return g(x); 9 } 10 11 int main(void) 12 { 13 return f(8) + 1; 14 }
编译命令:
gcc -S -o main.s main.c -m32
编译得到的汇编代码:
.file "main.c" .text .globl g .type g, @function g: .LFB0: .cfi_startproc pushl %ebp .cfi_def_cfa_offset 8 .cfi_offset 5, -8 movl %esp, %ebp .cfi_def_cfa_register 5 movl 8(%ebp), %eax addl $3, %eax popl %ebp .cfi_restore 5 .cfi_def_cfa 4, 4 ret .cfi_endproc .LFE0: .size g, .-g .globl f .type f, @function f: .LFB1: .cfi_startproc pushl %ebp .cfi_def_cfa_offset 8 .cfi_offset 5, -8 movl %esp, %ebp .cfi_def_cfa_register 5 subl $4, %esp movl 8(%ebp), %eax movl %eax, (%esp) call g leave .cfi_restore 5 .cfi_def_cfa 4, 4 ret .cfi_endproc .LFE1: .size f, .-f .globl main .type main, @function main: .LFB2: .cfi_startproc pushl %ebp .cfi_def_cfa_offset 8 .cfi_offset 5, -8 movl %esp, %ebp .cfi_def_cfa_register 5 subl $4, %esp movl $8, (%esp) call f addl $1, %eax leave .cfi_restore 5 .cfi_def_cfa 4, 4 ret .cfi_endproc .LFE2: .size main, .-main .ident "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2" .section .note.GNU-stack,"",@progbits
过滤掉其中的伪代码指令:
cat main.s | grep -v "\."
得到干净的汇编代码:
g: pushl %ebp movl %esp, %ebp movl 8(%ebp), %eax addl $3, %eax popl %ebp ret f: pushl %ebp movl %esp, %ebp subl $4, %esp movl 8(%ebp), %eax movl %eax, (%esp) call g leave ret main: pushl %ebp movl %esp, %ebp subl $4, %esp movl $8, (%esp) call f addl $1, %eax leave ret
下面对得到的干净的汇编代码进行分析:
main: pushl %ebp # (%esp) - 4 -> %esp; (%ebp) -> (%esp) movl %esp, %ebp # (%esp) -> %ebp subl $4, %esp # (%esp) - 4 -> %esp movl $8, (%esp) # 8 -> (%esp) call f # (%esp) - 4 -> %esp; (%eip) -> (%esp); f -> %eip
f:
pushl %ebp # (%esp) - 4 -> %esp; (%ebp) -> (%esp)
movl %esp, %ebp # (%esp) -> %ebp
subl $4, %esp # (%esp) - 4 -> %esp
movl 8(%ebp), %eax # (%ebp + 8) -> %eax
movl %eax, (%esp) # (%eax) -> (%esp)
call g # (%esp) - 4 -> %esp; (%eip) -> (%esp); g -> %eip
g:
pushl %ebp # (%esp) - 4 -> %esp; (%ebp) -> (%esp)
movl %esp, %ebp # (%esp) -> %ebp
movl 8(%ebp), %eax # (%ebp + 8) -> %eax
addl $3, %eax # (%eax) + 3 -> %eax
popl %ebp # (%esp) -> %ebp; (%esp) + 4 -> %esp
ret # (%esp) -> %eip; (%esp) + 4 -> %esp
leave # (%ebp) -> %esp; (%esp) + 4 -> %esp
ret # (%ebp) -> %esp; (%esp) -> %ebp; (%esp) + 4 -> %esp
addl $1, %eax # (%eax) + 1 -> %eax leave # (%ebp) -> %esp; (%esp) -> %ebp; (%esp) + 4 -> %esp; ret # (%esp) -> %eip; (%esp) + 4 -> %esp
关于上述分析的几点说明:
上述汇编代码按照程序执行流进行排列的, 每行汇编代码右侧的注释说明了该行汇编代码所完成的操作及执行后的效果。上述注释代码中出现在‘->‘左侧的是一个值,出现在‘->‘右侧的是一个地址, 表示将左侧的值写入到右侧的地址中。
总结
通过对一个简单的C程序的汇编代码进行分析, 对计算机工作过程有了更深的理解: CS:EIP确定了CPU执行流!
标签:
原文地址:http://www.cnblogs.com/long3216/p/4322221.html