本课题来源:网易云课堂《Linux内核分析》
地址:https://mooc.study.163.com/learn/1000029000?tid=2403023011&_trace_c_p_k2_=b007fad39e354f55af484d41391c5783#/learn/announce
关键字:栈,函数,调用,汇编,寄存器
概述:C语言程序介于汇编语言和高级语言中间面,拥有直接操纵内存入口,同时拥有高级语言易读性。这里我们将通过汇编角度探索程序执行开始、结尾、中间入栈出栈操作。
正文:
原始C程序
对应汇编程序
32位机器对应汇编指令
一、基础知识补充:
1.1、32位机汇编指令:movl、subl、addl、pushl、popl、call、leave、ret
movl %ebp, %esp 将ebp中内容放置到esp中。
subl $4, %esp 寄存器esp值减少4。
addl $1, %eax 寄存器eax中值增加1。
popl %ebp 栈顶内容保存到ebp中,之后esp寄存器数值加4。
pushl %ebp 将ebp中内容入栈,之后esp寄存器值减4。
call f 先将eip指向地址入栈(call f 下一条指令位置),之后eip指向f地址位置。
pushl %eip
movl f , %eip
leave 将ebp中的内容移动到esp中去,之后出栈内容到ebp中。
movl %ebp, %esp
popl %ebp
ret 出栈内容到eip中。
popl %eip
1.2 、相关寄存器:ebp、esp、eip
ebp 段寄存器,保存栈基址。
esp 保存当前栈顶地址。
eip 存放在执行指令的下一条指令地址。 cs:eip唯一确定一条指令。
1.3、栈
栈结构
新增数据入栈,栈顶指针向下移动,寄存器esp中的值减少4。数据出栈,栈顶指针向上移动,寄存器esp中的值增加4。
二、剖析汇编程序
2.1、 程序入栈
程序找到main函数入口,即cs:eip指向位置
pushl %ebp
ebp入栈
movl %esp,%ebp
esp值赋予ebp
subl $4 ,%esp
栈顶指针向下移动一个存储单元
movl $5, (%esp)
数据存放到esp所指向位置
call f :2条指令集合,pushl %eip 、 movl f , %eip
eip值入栈(call f下一条指令地址)
对eip重新赋值,指向f函数入口地址
将先前ebp所指向地址入栈(main)
将ebp指向新的函数入口(f)
subl$4, %esp
esp指针向下移动一个位置
movl 8(%ebp),%eax
eax接收函数返回值5
movl %eax,(%esp)
main函数传递参数到f
call g
pushl %eip
call g下一跳指令地址入栈 15
movl f,%eip
eip指向将要执行的指令即 g函数位置
pushl%ebp
movl%esp, %ebp
movl8(%ebp), %eax
addl $6,%eax
以上4条执行完,即函数入栈全部结束
2.2、程序出栈
popl %ebp
返回f函数入口处
ret
下一条执行指令位置为leave
leave
栈顶指向ebp位置
弹出f函数
ebp指向main函数入口位置
ret
执行指令转到main程序
addl $1,%eax
最终返回值位11+1=12
leave
popl %ebp
程序栈基址返回系统掉用入口
ret
执行程序返回到系统调用下一条指令
至此函数生命周期全部完成
三、总结与展望
第一次对于函数入栈出栈有了大体认识,了解了为什么程序会有生命周期,函数会有生命周期。巧妙的设计方法都有待学习。
本例程序中仍有很多地方认识不是特别到位,留下足迹,记录自己成为大牛历程。
举报/反馈