计算机是如何工作的?--通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的

王康 原创作品转载请注明出处 《Linux内核分析》MOOC课程 http://mooc.study.163.com/course/USTC-1000029000

 

1 存储程序计算机模型

cpu内部有寄存器ip,分别在16位叫 ip 32 eip 64rip

ip通过总线指向代码段一个地址,取过来一条指令执行;

执行完之后ip取下一条指令自加一继续指向。

硬件来看:冯诺依曼通用

软件程序员来看:

wps246.tmp

内存存储指令和数据,cpu执行指令

cpu识别什么样的指令?

API:程序员与计算机接口界面

ABI:二进制接口,程序与CPU接口界面---汇编指令---

----指令中涉及一个寄存器,内存地址

wps247.tmp

1 eip自加一,是加一条指令而不是地址加一(因为指令长度可能不同);

2 eip可以被CALL,RET,JMP指令可以修改eip

注意:
1.程序员不可以直接修改IP的值,只能通过一些指令,如CALL、RET、JMP等间接修改IP的值
2.IP在32位机器中表示为eip(本次实验以32位作为分析),在64位机器中表示为rip。

 

 

2 x86汇编基础

wpsF7E3.tmp

开头e为32位 ebx+ecx偏移地址  ebp esp堆栈  

以上为通用寄存器,还有段寄存器

wpsF7E4.tmp

wpsF7E5.tmp

还有一个标志寄存器

wpsF7E6.tmp

wpsF7E7.tmp

64位差别不大,通用寄存器扩展到64位,前边带R就是扩展了的

还增加了一些64位的MMX的寄存器。

使用只是寄存器名字不一样,机制差别不大

wpsF7E8.tmp

movl 32位 movb8位 movw16位 mowq 64位

wpsF7F9.tmp

wpsF7FA.tmp

$0x123 16进制的数值放到edx里边,也和内存没有关系

wpsF7FB.tmp

没有$就表示一个地址放到,后边就是c语言相同表示:

wpsF7FC.tmp将0x123数值强制转化为32位的一个int变量指针,再用*取他指向的值

wpsF7FD.tmp

可以看到c语言模式一样的,也是转地址

wpsF7FE.tmp

wpsF7FF.tmp

wpsF800.tmp

wpsF801.tmp

push 把eax压倒堆栈栈低,等同于:esp是堆栈栈低,减4,4字节就是32位,且堆栈是向下增长。最后把eax压入

wpsF812.tmp

pop:把栈顶数值放入eax,然后把esp加四,向上回退

wpsF813.tmp

call:把当前eip压栈保存起来,赋了一个新值

wpsF814.tmp

ret:pop eip实际就是执行了一个call,call到了函数定义的位置。

pop就是把call时候保存的eip再返回到eip指令当中来,继续执行当时函数调用的下下一跳指令.

(*)意思是伪指令,不能被程序员直接修改

wpsF815.tmp比如call指令,ret指令

push eip(*)意思是把当前eip值压入;而ret: pop eip时候会把弹出的值自动赋值到eip寄存器

 

 

3 汇编一个简单的c程序分析其汇编指令执行过程

wps49BB.tmp

吧当前main.c编译为32位。-S为生成编译文件

main.s所有用.开头是连接时候辅助信息

wps38EE.tmpwps38EF.tmpwps38F0.tmp

wps38F1.tmp

wps49CC.tmp

wps49CD.tmp

wps49CE.tmp

这两条可以认为是宏指令,一个是函数调用一个是函数退出,正好相反

wps49CF.tmp

wps49D0.tmp

 

实验分析:

wps49D1.tmp

第二条和第一条就是enter

call f:对应push eip(执行这个动作时候eip实际指向的下一条地址)和mov f地址到eip

wps49E1.tmp

可以看到指向了23位置

执行f:10行代码以后:

wps49E2.tmp

12条是把8赋值给eax,eax = 8

13条把8放到了标号5的位置

call g :push eip(此时eip应该是15行代码位置);

wps49E3.tmp

执行第三行后:

wps49F4.tmp

pop ebp实际就是把ebp 4 内容放回ebp,效果就是ebp又指向原来4的位置,

同样esp要减4又指向6号标号位置

ret--- pop eip:esp指向标号5位置同时eip指向了15(call下一条指令)

最后leave。esp和ebp都指向4

wps49F5.tmp

wps49F6.tmp

pop后esp+4指向3位置

wps49F7.tmp

最后ret。

wps49F8.tmp

eip指向了23,

addl:eax是默认返回值,eax = 12

leave:最后都指向1,再pop ebp,则均指向0

wps49F9.tmp

有两点需要注意的地方:

1 函数调用之所以把8放到下一个栈帧ebp+8的位置是因为参数位置是紧跟下一个方法调用栈帧位置,例如当前ebp和esp之间空出了2个位置,那么8参数要放到靠下紧贴下一个方法调用栈帧位置

2 另外eax是调用者保存寄存器caller save,所以过程中不需要去管eax

 

 

4、实验总结–对计算机如何工作的理解
1.计算机的基本原理是存储程序和程序控制,预先要把指挥计算机如何进行操作的指令序列(称为程序)和原始数据通过输入设备输送到计算机内存贮器中。每一条指令中明确规定了计算机从哪个地址取数,进行什么操作,然后送到什么地址去等步骤。
计算机在运行时,先从内存中取出第一条指令,通过控制器的译码,按指令的要求,从存储器中取出数据进行指定的运算和逻辑操作等加工,然后再按地址把结果送到内存中去。接下来,再取出第二条指令,在控制器的指挥下完成规定操作。依此进行下去。直至遇到停止指令。简单来说就是CPU负责处理和运算,存储器负责保存指令和数据。通过操作系统得调度和安排,不停地进行取址、译码、执行的循环。
2.汇编代码是什么?
计算机语言的发展过程从机器语言(计算机能直接识别的二进制0和1的组合)->汇编语言(为了减轻使用机器语言编程的痛苦,人们进行了一种有益的改进:用一些简洁的英文字母、符号串来替代一个特定的指令的二进制串,依赖于硬件)->高级语言(接近于数学语言或人的自然语言,同时又不依赖于计算机硬件,编出的程序能在所有机器上通用)。
我们编写了一个小程序,比如上面实验中写到的main.c文件,编译器执行的过程,这里写图片描述
可执行的二进制文件是计算机“认识”的文件,可以直接执行。
3.以上便是我对这次实验的总结,计算机很“单纯”,它可以执行很多复杂的指令,但它也是被“告诉”要执行什么,才会去执行什么,通过对汇编语言的分析可以方便我们理解计算机处理的过程,了解计算机如何工作等等。感谢为我们辛苦准备课程的老师!

posted on 2017-02-21 13:29  wk2016just  阅读(244)  评论(0编辑  收藏  举报