实验
源代码:
int g(int x)
{
return x + 4;
}
int f(int x)
{
return g(x);
}
int main()
{
return f(10) + 3;
}
输入:
gcc -S -o main.s main.c -m32
反汇编代码:
.file "201504411_\345\217\215\346\261\207\347\274\226.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 $4, %eax
popl %ebp
.cfi_def_cfa 4, 4
.cfi_restore 5
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 $10, (%esp)
call f
addl $3, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE2:
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
.section .note.GNU-stack,"",@progbits
g函数:
f函数:
main函数:
堆栈的变化
寄存器 | 内容 | 地址 |
---|---|---|
空 | 空 | 0 |
空 | ebp = 0 | 4 |
空 | 10 | 8 |
空 | eip = 56 (addl $3, %eax) | 12 |
空 | ebp = 4 | 16 |
空 | 10 | 20 |
空 | eip = 36 (leave) | 24 |
esp-> | ebp = 4 | 28 |
然后不断地出栈
计算机如何工作
如今的计算机处理器的结构主要分为两类,一类是冯·诺伊曼结构,一类是哈佛结构。
其中冯·诺伊曼结构是一种将程序指令存储器和数据存储器合并在一起的结构,哈佛结构是一种将程序指令和数据分开存储的结构,无论哪种结构,一般的流程都是cpu到存储器中读取程序指令,然后译码,执行,当需要数据时,再到存储器中读取数据。指令都是顺序执行,直到指令结束。