Linux内核分析——第一周学习笔记20135308
2016-02-22 23:38
543 查看
第一周 计算机是如何工作的
第一节 存储程序计算机工作模型
1、冯·诺依曼结构模型:冯·诺依曼结构也称普林斯顿结构,是一种将程序指令存储器和数据存储器合并在一起的存储器结构。程序指令存储地址和数据存储地址指向同一个存储器的不同物理位置,因此程序指令和数据的宽度相同。![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160222212637864-2117951512.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160222211850192-72123745.jpg)
2、CPU可以抽象成一个for循环,总是从内存中执行下一条指令。
内存:保存指令数据
CPU:解释执行指令、数据
内存与CPU通过总线连接。
API:应用程序编程接口
ABI:二进制(指令编码)接口
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160222212346520-1983869870.jpg)
例如:32位计算机X86,EIP指向内存的某条指令
1、自+1,即自动加到下一条指令
2、可被其他指令修改,如CALL,RET,JMP等。
第二节 X86汇编基础
一、X86 CPU的寄存器
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160222213008145-452396126.jpg)
如上图,是一个32位寄存器。
16位寄存器:AX,BX,CX,DX,BP,SI,DI,SP等
32位寄存器:EAX累加寄存器,EBX基址寄存器,ECX技术寄存器等 前面加上E的均为32位寄存器。
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160222222634301-1178542984.jpg)
64位寄存器与32位寄存器区别不大,前面有R的为64位寄存器。
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160222222859723-1301864940.jpg)
二、mov指令及几种内存寻址方式
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160222223015895-576687880.jpg)
1、movl:l为32位
寄存器寻址%eax,%edx
即操作寄存器,与内存无关,相当于eax=edx
立即寻址$0x123,%edx
123这个16进制数值放进寄存器edx中($表示立即数)
直接寻址0x123,%edx
123这个地址指向寄存器edx(没有$表示地址)
间接寻址(%ebx),%edx
(%ebx)表示ebx这个寄存器存的值为内存地址
变值寻址4(%ebx),%edx
在间接寻址的基础上加上4
2、movb:b为8位
3、movw:w为16位
注意:
AT&T汇编格式与Intel汇编格式略有不同
Linux内核使用的是AT&T汇编格式
三、几个重要的汇编指令:push、pop、call、ret
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160222224210051-535179132.jpg)
1、pushl %eax
把eax压栈到堆栈栈底
即首先把esp减4
esp表示堆栈栈顶
ebp表示堆栈基址
2、popl %eax
把eax从堆栈栈顶取32位,放在寄存器eax中
即首先把栈顶esp的数值放在eax中,再把栈顶加4
3、call 0x12345
调用该地址
即将当前的eip(当前CPU执行命令的指针)压栈,赋给eip一个新值(CPU下一条执行的指令)
4、ret
即将call时保存的eip还原到eip寄存器,return call之前的那条指令
eip(*)这个*指程序员不能直接修改eip
四、分析一段汇编代码
1、![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160222231115254-1781111551.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160222232812285-1076397340.jpg)
2、
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160222231813160-1117128455.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160222232731692-1156649918.jpg)
3、
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160222232639239-1200552903.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160222232854754-720636451.jpg)
第三节 将C代码编译成汇编代码
实验:通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的
首先,通过vi编写luchang5308.c文件![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223115440115-1524637431.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223125752396-109408005.jpg)
通过gcc –S –o main.s main.c -m32命令将c文件编译成汇编代码
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223115544865-389783848.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223125805396-1746336688.jpg)
删除以.开头的说明语句
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223125817927-79903214.jpg)
P.S. enter指令与leave指令
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223130106865-1092803900.jpg)
P.S. 函数的返回值默认使用eax寄存器存储返回给上一级函数
过程分析:
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223184854693-366613188.jpg)
把ebp的值0压入栈,esp减4,指向下一个位置
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223185447615-129645366.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223185730115-1456687841.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223185846286-2008662032.jpg)
esp的值赋给ebp,这样,ebp也指向标号1的位置
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223190039380-658666819.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223190131099-1154918061.jpg)
esp向下移动一个标号,指向2
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223190244224-1030984320.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223190339161-1813852827.jpg)
将立即数6放在esp所指的位置
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223192753271-1801384576.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223192832818-126142999.jpg)
call命令包含
1.push eip
2.mov f eip
执行call命令,eip指向下一条指令,即23行代码,将eip压栈,eip指向f函数,指令从f函数开始执行,esp指向标号3的位置。
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223210226490-576850129.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223193633396-34804510.jpg)
将ebp压栈,esp指向标号为4的位置
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223210437505-199812891.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223193952818-119852153.jpg)
将esp的值赋给ebp
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223210534099-1258323395.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223194340833-1570471855.jpg)
esp指向下一个位置,即标号为5的地方
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223210651318-945114838.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223194847146-1573288390.jpg)
ebp变址寻址8,即ebp从标号为4的地方,向上移动2个位置,内容为6,所以eax=6
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223210703974-1709202197.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223195356536-252556257.jpg)
把eax放在esp的位置,即5的位置
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223214114208-360732330.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223195703880-1375032626.jpg)
push eip
调用g函数,esp标号向下移动一位,标号为6的位置,eip15压栈,此时eip指向g函数
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223220611974-342014678.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223203740286-410128351.jpg)
将ebp的值压栈
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223220837693-1837748526.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223205706036-1721889798.jpg)
把ebp指向esp所在的位置
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223221002896-1966374547.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223211752740-881133442.jpg)
ebp上两个位置的值赋给eax,eax=6
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223221022583-1981069891.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223213333161-60205957.jpg)
eax加4,eax=10
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223221037786-682424735.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223215020021-1602600849.jpg)
弹栈,把ebp(4)放回ebp,即让ebp又指向了4的位置。同时,esp加4,指向6。
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223221145490-469053548.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223215909802-1178499654.jpg)
ret即popl %eip,此时eip所存为15,esp指向标号5的位置,同时eip指向了15
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223221316786-1111112480.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223221351349-894601106.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223221418786-573098542.jpg)
ebp指向4,esp也指向4,ebp弹栈,ebp指向1,esp加4,指向3
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223221644255-1577906605.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223221720286-938181336.jpg)
popl %eip eip为23,esp加4,指向2
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223222009833-2132381712.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223222033724-1254197708.jpg)
eax加3,eax=13
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223222142880-536388984.jpg)
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223222211161-1085969374.jpg)
movl %ebp,%esp
popl %ebp
首先,ebp,esp均指向了1
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223222356740-1679510017.jpg)
然后,ebp指向0,esp减4,指向0,回到了main函数最初的状态
![](http://images2015.cnblogs.com/blog/745043/201602/745043-20160223222530521-1243579243.jpg)
该程序堆栈执行完毕
总结
对“计算机是如何工作的”理解
1、冯·诺依曼提出程序存储的思想,程序与数据一样存贮,按程序编排的顺序,一步一步地取出指令,自动地完成指令规定的操作是计算机最基本的工作原理。2、CPU可以抽象成一个for循环,总是从内存中执行下一条指令。内存负责保存指令数据,CPU负责解释执行指令、数据。内存与CPU通过总线连接。
3、通过使用高级语言,应用汇编语言,机器语言的编译,即计算机在运行时,先从内存中取出第一条指令,通过控制器的译码,按指令的要求,从存储器中取出数据进行指定的运算和逻辑操作等加工,然后再按地址把结果送到内存中去。接下来,再取出第二条指令,在控制器的指挥下完成规定操作。最终将指令的结果放入寄存器中。
攥写人:芦畅 学号:20135308
原创作品转载请注明出处
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
相关文章推荐
- linux运维经验~~基础篇非常适合入门
- Linux软件安装管理
- Linux软连接与硬连接
- CentOS搭建SVN服务器
- 学习Linux计划书
- Git clone wiringPi出现Connection reset by peer的解决办法
- Linux学习笔记(7)----数据流重定向
- Linux就这个范儿 第8章 我是Makefile
- Linux 命令之查看和修改机器名称
- 制作initrd(5):解剖Ubuntu安装盘
- Linux 环境变量
- Linux kamailio Sip服务器的编译与安装(Ubuntu14.04)
- Linux下C语言字符串操作之分割字符串总结
- linux uart
- CentOS 没有root权限下Caffe 安装的小问题
- Linux中如何添加/删除FTP用户并设置权限
- Linux X11 程序下都有神马
- 学习Linux计划书
- 《超级优化Linux远程SSH连接》
- gitlab install centos 详细步骤!