分类: LINUX
2011-12-22 21:52:37
基础知识
汇编语言的组成:
汇编由以下三类指令组成。
1. 汇编指令:机器码的助记符,有对应的机器玛
2. 伪指令:没有对应的机器码,由编译器执行,计算机并不执行。
3. 其他符号:如+、-、*、/等,由编译器识别,没有对应的机器码。
汇编语言的核心是边边指令,它决定了汇编语言的特性。
要让一个CPU工作,就必须行他提供指令和数据,指令和数据在存储器中存放,也就是我们平时所说的内存。指令和数据是应用上的概念,在内存或磁盘上,指令和是沪剧没有任何区别,都是二进制信息,CPU在工作时把有的信息看做指令,有的信息看做数据,为同样的信息赋予不同的意义。就象围棋的棋子,在棋盒里是没有任何区别的,在对弈时就有了不同的意义。
存储器
存储器被划分为若干个存储单元,每个存储单元从0开始顺序编号,计算机最小的单位为BIT (比特),也就是一个二进制位,8个比特组成一个字节,微型机存储器的存储单元可以存储一个比特,即8个二进制位,一个存储器有128个存储单元,他可以存储128个字节。
CPU要从内存中读数据,首先要指定存储单元的地址,也就是说他要先确定他要读哪一个存储单元中的数据,另外一个计算机中不只有一种存储器。CPU在读写数据时还要指明,他要对哪一个器件进行操作,进行哪种操作,是从中读还是写。
可见CPU要想进行数据的读写,必须和外部的器件(标准的说法是芯片)进行下面三累信息交互。
一、存储单元的地址(地址信息)
二、器件的选择,读或写的命令(控制信息)
三、读或写的数据(数据信息 )
地址总线
CPU是通过地址总线来指定存储单元的,可见地址总线上能传诵多少个不同的信息,CPU就可以对多少个存储单元进行寻址。
通过地址总线的大小来确定他的寻址范围,一CPU有10根地址总线,让我们来看一下他的寻址情况,我们知道计算机中一根导线可以传诵的稳定状态为两种,一种是高电平,一种是低电平,二进制的1或0,10根导线可以传诵10位二进制的数据,而10位二进制可以表示多少个不同的是数据呢?2的10次方个。最小为0。最大为1023。一个CPU有N根地址线,则说这个CPU的地址总线宽度为N,这样的CPU最多可以寻找2的N次方个内存单元。
数据总线
CPU与内存或其他器件之间的数据传诵是通过数据总线来进行的,数据总线的宽度决定了CPU和外界的数据传送速度,8根数据总线一次可从送一个8位的二进制数据(一个字节)16根数据总线一次可传诵两个字节
8088CPU的数据总线宽度为8。8086CPU的数据总线宽度为16。
控制总线
CPU对外部的器件的控制是通过控制总线来进行的,在这里控制总线是个总称,控制总线是一些不同的控制线的集合,有多少根控制总线,就以为着CPU提供了对外部器件的多少种控制,所以,控制总线的宽度决定了CPU对外部器件的控制能力。
内存读或写是由几根控制线综合发出的,其中有一根称为读信号输出的控制线负责CPU向外传诵信号,CPU向该控制线上的输出低电平表示将要读取数据。有一根称为写信号输出的控制线则负责传诵写信号
每一个CPU芯片都有许多的管脚。就可以说这些管脚是引出总线。一个CPU可以引出3种总线的宽度称标志这个CPU的不同方面的性能。
地址总线的宽度决定了CPU的寻址能力
数据总线的宽度决定了CPU与其他器件的进行数据传诵时的一次数据传送量
控制总线的宽度决定了CPU对系统中的其他器件的控制能力
内存空间地址
什么是内存地址空间?一个CPU的地址总线为10。那么可以寻址1024个内存单元,这1024个可寻到的内存单元就构成这个CPU的内存地址空间。
最终运行程序的时候是CPU,我们用汇编语言变成的时候,必须要从CPU的角度考虑问题,对CPU来讲。系统中的所有存储器件的存储单元都处于一个统一的逻辑存储器中,他的容量受CPU寻址能力的限制。这个逻辑存储器即我们所说的内存空间。
一个典型的CPU由运算器、控制器、寄存器、等器件构成。这些器件靠内部总线相连。相对来讲控制总线、数据总线、地址总线为外部总线。而这些总线为内部总线。
简单的说。在CPU中
运算器进行信息处理
寄存器进行信息储存
控制器控制各种器件进行工作
内部总线连接各种器件,在它们之间进行数据的传诵
寄存器
对于一个汇编程序员来讲。CPU中的主要部件是寄存器,寄存器是CPU中程序员可用指令读写的部件,程序员通过改变各种寄存器中的内容来实现对CPU的控制。
不同的CPU,寄存器的个数、结构是不相同的。8086CPU有14个寄存器。每个寄存器都有一个名称。这些寄存器为:AX、BX、CX、DX、SI、DI、SP、BP、IP、CS、SS、DS、ES、PSW。
通用寄存器
8086的所有寄存器都是16位的,可以存放两个字节。AX、BX、CX、DX这四个寄存器通常用来存放一般性的数据。被称为通用寄存器。
AX 、BX、CX、DX是16位寄存器,又可以分为独立的两个8位寄存器 AH 、AL、BH、BL、CH、CL、DH、DL
高八位为H 低八位为L
在进行传送或者运算时,对应的寄存器的位数也应该一样,如MOV AL,BX是错误的,BX是16位寄存器,AL为8位。位数不等。、
物理地址
CPU访问内存单元时,要给出内存单元的地址,所有的内存单元构成的存储空间是一个一维的线性空间,每一个内存单元在这个空间中都有一个唯一的地址,我们将这个唯一的地址称为物理地址。
CPU通过地址总县送入存储器的,必须是一个内存单元的物理地址,在CPU向地址总线发出物理地址之前,必须要在内部先形成这个物理地址,不同的CPU可以有不同的形成物理地址的方式。
16位CPU
概括的讲,16位结构(16位机、字长16位),描述了一个CPU具有下面几方面的结构特性
运算器一次最多可以处理16位数据
寄存器的最大宽度为16位
寄存器和运算器之间的通路为16位
8086CPU内部用两个16位地址合成的方法来形成一个20位的物理地址。
当8086CPU要读写内存时:
CPU中的相关部件提供两个16位地址,一个称为段地址,另一个称为偏移地址
段地址和偏移地址通过内存总线送入一个称为地址加法器的部件
地址加法器将两个16位地址合成一个20位物理地址
地址加法器通过内部总线将20位物理地址送入输入输出控制电路
输入输出控制电路将20位物理地址送上地址总线
20位物理地址被地址总线传送到寄存器
地址加法器采用物理地址=段地址*16+偏移地址的方法用段地址和偏移地址合成物理地址。段地址*16 有一个更为常用的说法是左移4位,计算机中的所有信息都是以二禁止的形式存储的 。段地址也不例外,机器只能处理二禁止信息。左移4位中的位是2进制位。
一个数的二进制形式左移一位,相当与该数据乘以2
一个数的二进制形式左移N位,相当于该数据乘以2的N次方
一个数据的十六禁止左移一位,相当于乘以16。一个十进制的形式左移一位。相当于乘10,一个X进制的数据左移一位,相当于乘以X
段地址*16+偏移地址=物理地址的本质含义:CPU在访问内存时,用一个基础地址(段地址*16)和一个相对于基础地址的偏移地址相加,给出内存单元的物理地址。更简单的说,8086CPU的这种寻址功能是“基础地址+偏移地址=物理地址”寻址模式的一种具体实现方案,8086CPU中,段地址*16可看作基础地址
可能还是不理解偏移地址这个概念,这个概念确实比较抽象。
物理地址
D E
a b c
ab=基础地址 bc=偏移地址
比如DE=1000 ab=800 bc=200 ,可以把ab当作相对于起点的基础地址(已a点为起点)800,bc相当于基础地址的偏移地址200(已基础地址ab为起点)
段的概念
段地址包含段的概念,但是内存并没有被分段,段的划分来自CPU,由于8086CPU用“段地址*16+偏移地址=物理地址”的方式给出内存单元的物理地址。使我们可以用分段的方式来管理内存。地址:10000H-100FFH 的内存单元组成一个段,这段的起始地址(基础地址)为10000H,段地址为1000H,段大小为100H,以后,在变成时可以根据需要,将若干地址连续的内存单元看作一个段,用段的地址*16定位段的起始地址(基础地址),用偏移地址定位段中的内存单元,有两点需要注意:段地址*16必然是16的倍数,所以一个段的起始地址也一定是16的倍数:偏移地址为16位,16位地址的寻址能力为64KB,所以一个段的长度最大为64KB
段寄存器:
CS和IP是8086CPU中两个最关键的寄存器,他们指示了CPU当前要读取指令的地址,CS为代码段寄存器,IP为指令指针寄存器,从名称上我们可以看出他们和指令的关系,8086CPU,任意时刻。都是从内存CS*16+IP单元开始,读取一条指令并执行。也可以这样理解,8086机中,任意时刻,CPU将CS:IP指向的内容当作指令执行。
从CS:IP指向的的内存单元读取指令,读取的指令进入指令缓冲器,并执行,IP的值发生改变,IP=IP+所读取的指令的长度,从而指向下一条指令,执行指令。重复这个过程。
我们以前学过在内存中,指令和数据都是以二进制存放的,什么时候CPU把二进制信息看成指令?什么时间把二进制信息看成数据?现在我们知道CS:IP指向的内存单元中的数据看成指令,因为在任意时候CPU将CS、IP中的内容当作指令的段地址和偏移地址,用他们合成指令的物理地址,到内存中读取指令码,如果说,内存中的一段信息曾被CPU执行过的话,那么,他所在的内存单元必然被CS:IP指向过。
修改CS、IP
在CPU中,程序员能够用指令读写的部件只有寄存器,程序员可以通过改变寄存器的中的内容实现对CPU的控制,CPU中何处执行指令由CS、IP中的内容决定,程序员可通过改变CS、IP中的内容来控制CPU执行的目标指令。MOV指令不可以直接修改CS寄存器的值,为什么呢,原因很简单,8086CPU没有提供这样的功能。那怎样来修改CS:IP的值呢,用JMP指令。
用法:JMP 段地址:偏移地址 功能为:用指令中给出的段地址修改CS,偏移地址修改IP。
如果只想修改IP的值,可以用:JMP 某一合法的寄存器 功能为:用寄存器的值修改IP
前面讲过,在编程时,可以根据需要,将一组内存单元定义为一个段,我们可以把长度为N(N<=64KB)的一组代码,存在一组地址连续、起始地址为16的倍数的内存单元中,我们可以认为,这段内存是用来存放代码的,从而定义了一个代码段。
查看CPU和内存,debug的使用(这部分大家一定要亲手去实践、操作,不然是很难明白的
用DEBUG的R命令查看、改变CPU寄存器的内容。
用DEBUG的D命令来查看内存中的内容。
用DEBUG的E命令来改写内存中的内容(16进制)
用DEBUG的U命令将内存中的机器指令翻译成汇编指令
用DEBUG的T命令执行一条汇编指令
用DEBUG的A命令以汇编指令的格式在内存中写入一条机器指令
寄存器(内存访问)
内存中字的存储
DS和[address]
字的传递
Mov、add、sub
数据段
栈和CPU提供的栈机制
栈顶超界问题
Push、pop指令
栈段
[BX]和LOOP指令
[bx]
Loop指令
Debug和masm对指令的不同处理
Loop和[bx]的联合应用
段前缀
一段安全空间
段前缀的使用