郑卓彬 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
前言:
第一节课,老师讲了冯诺依曼计算机的程序执行流程,以及部分汇编指令,和汇编代码中的函数栈。
计算机程序运行:
冯诺依曼计算机,分为运算器、控制器、存储器、输入设备、输出设备五部分。其中运算器、控制器就是计算机中的cpu,cpu中有寄存器、程序计数器。当程序在计算机中运行时,cpu中的ip寄存器存储着下一条指令的地址,每当一条指令执行完,cpu就从ip寄存器中取出相应指令的地址进行解析执行,并且ip自动加一指向下一条需要执行指令的地址。
汇编基础:
汇编语言是较为底层的语言,也是计算机指令与高级语言的接口,本章学习了基础的汇编命令和8086cpu的各个寄存器作用。
寄存器作用:
汇编指令:
解析: mov指令,用于将 源 里的数据传到 目的 其中该指令的源在 后面跟着的左半部分,目的在右半部分。 但是根据寻址模式的不同,会传回不同的参数,如寄存器模式就是将前一个寄存器中的值传入后一个寄存器,立即数寻址就是将该数字传到目的等。
解析: 如图,左边的一条指令就相当与右边的多条指令。
实验例子:
对于如下的c代码 :
可用 gcc 解析为中间文件,并将,将中间文件中的带.开头的句子删除,就剩下这c程序对应的汇编代码了:
对应汇编代码:
汇编代码如上,各个分段对应图四的函数。
汇编代码基础:
1、每个函数的调用都会在该程序的栈中添加一个函数栈区,用来保存该函数的上下文。
2、ebp和esp寄存器:ebp寄存器指向该函数栈的栈底,且栈底的内容存储的是上一个栈底的地址。esp的内容是栈顶的地址。
汇编代码解析:
1、main函数:
pushl %ebp
movl%esp, %ebp #以上两条语句,将的ebp中的内容存到栈中做栈底,并把ebp重新指向该栈底
subl$4,%esp
movl$2,(%esp) #以上两条语句将数2压栈
call f #调用f函数,是将eip中的值压栈(函数调用回来后要执行的指令),并将f函数 的地址存入eip
addl$3,%eax #将传回的数与立即数3相加
leave #将栈顶地址变为栈底地址,也就是使该栈成为空栈,并将ebp寄存器中的值改 为上个栈底
ret #结束
2、f函数:
pushl %ebp
movl%esp, %ebp #以上两条语句,将的ebp中的内容存到栈中做栈底,并把ebp重新指向该栈底
subl$4,%esp
movl8(%ebp), %eax
movl%eax, (%esp) #以上三条语句将main函数中压栈的值2给取到eax寄存器中,并且将该值也压到f 函数的栈中
call g #调用g函数,是将eip中的值压栈(函数调用回来后要执行的指令),并将f函数 的地址存入eip
leave #将栈顶地址变为栈底地址,也就是使该栈成为空栈,并将ebp寄存器中的值改 为上个栈底
ret #将main函数压栈的eip值返回到eip寄存器中,既继续执行调用main函数的下面一 条指令
3、g函数:
pushl %ebp
movl%esp, %ebp #以上两条语句,将的ebp中的内容存到栈中做栈底,并把ebp重新指向该栈底
movl8(%ebp), %eax
addl$1,%eax #以上两条语句将f函数中压栈的值2给取到eax寄存器中,并且加一,用于返回
popl %ebp #弹出f函数的栈底到ebp中
ret #将f函数压栈的eip值返回到eip寄存器中,既继续执行调用f函数的下面一条指令
总结:
我理解的计算机其实是很笨的,一直的动作就是取指令,运行,取指令,运行。计算机之所以能体现的较为智能,是程序员一步步迭代的过程,程序员将显示生活中存在的实物或者抽象和逻辑用高级语言编写出来。所以计算机其实是人的思想的体现,只是他能之分认真的执行工作,可以24小时执行且基本不出错。
真实姓名(与最后申请证书的姓名务必一致) + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000