您的位置:首页 > 其它

第2章 寄存器(CPU工作原理)

2010-12-31 19:28 155 查看
1. CPU中的运算器做信息处理;寄存器进行信息存储;控制器控制各种器件进行工作;内部总线连接各器件,在它们之间进行数据的传送。对于汇编程序员来说,CPU中的主要部件是寄存器。寄存器是CPU中程序员可以用指令读写的部件,并通过改变各种寄存器的内容来实现对CPU的控制。 8086CPU(16位CPU)有14个寄存器,分别是:AX,BX,CD,DX,SI,DI,SP,BP,IP,CS,SS,DS,ES和PSW。 每个寄存器又可分成两个寄存器,一个是高位,一个是低位。如AX,可分成AH,AL两个寄存器,如下图:

AX的低8位(0位-7位)构成了AL寄存器,高8位(8位-15位)构成了AH寄存器。AH和AL是可以独立使用的8位寄存器。存储形式如下图:

一个16位寄存器所能存储数据的最大值是:2 ^ 16 - 1 = 65535,8位寄存器所能存储数据的最大值是:2 ^ 8 – 1 = 255 2. mov, add 指令 格式: mov 目标寄存器, 源数据(可以是常量值或寄存名) ; 将源数据存入目标寄存器中
add 目标寄存器,源数据(可以是常量值或寄存名) ; 将源数据与目标寄存器中的数据相加,结果存入目标寄存器中
如: mov ax, 18 ; 将18送入寄存器AX
mov ah, 78 ; 将78送入寄存器AH
add ax, 8 ; 将寄存器AX中的数值加上8
mov ax, bx ; 将寄存器BX中的数据送入寄存器AX
add ax, bx ; 将AX和BX中的数值相加,结果存在AX中 注:汇编语言中不区分大小写,mov ax, 18 与 MOV AX, 18 是等价的 3. 物理地址 8086是16位结构的CPU,有如下结构特性:
1.) 运算器一次最多可处理16位的数据
2.) 寄存器的最大宽度为16位
3.) 寄存器的运算器之间的通路为16位 而8086 CPU的地址总线是20位的,可以传送20位地址,寻址能力是1MB。而CPU内部结构是16位的,寻址能力只有64KB,具体如下图:

上图的8086 CPU读写内存示意图分如下步骤:
1.) CPU提供两个16位的地址,一个为段地址,一个为偏移地址;
2.) 段地址和偏移地址通过内部总线送入地址加法器;
3.) 地址加法器将两个16位地址合成为一个20位的物理地址;
4.) 地址加法器再通过内部总线把20位的物理地址送入输入输出控制电路;
5.) 输入输出控制电路将20位物理地址送上地址总线;
6.) 最后, 20位物理地址被地址总线传送到存储器 4. 物理地址的求法 地址加法器将两个16位地址合成为一个20位物理地址的方法是:
物理地址 = 段地址 * 16 + 偏移地址
如:8086 CPU要访问地址为:123C8H的内存单元,地址加法器所做的工作如下(以下地址均以16进制表示):
1. CPU先将123C8H 转换成段地址和偏移地址,段地址对应为1230,偏移地址对应为00C8,并传入给地址加法器; 2. 加法器将段地址*16,结果为:1230 * 16 = 12300 ; 3. 将段地址乘16后的结果与偏移地址相加:12300 + 00C8 = 123C8,得到物理地址 ; 4. 输出物理地址:123C8 段地址 * 16 + 偏移地址 = 物理地址的本质含义是:CPU在访问内存时,用一个基础地址(段地址 * 16)和一个相对基础地址的偏移地址相加,给出内存单元的物理地址。这也是8086 CPU的寻址方式,它以段地址 * 16看作是基础地址。 5. 段 事实上,内存并没有分段,段的划分来自于CPU,CPU通过分段的方式来管理内存。而采用分段管理内存的依据也是来自于CPU的寻址方式,即:物理地址 = 段地址 * 16 + 偏移地址。根据段地址 * 16为基础地址,一个段的起始地址也一定是16的倍数;偏移地址是16位,16位的寻址能力为64KB,所以一个段的长度最大为64KB。 而下图说明:CPU可以用不同的段地址和偏移地址形成同一个物理地址


再根据段的最大寻址能力为64KB,假如有段地址为:1000H,用偏移地址寻址,CPU的寻址范围为:1000H~1FFFFH。 在8086PC机中,存储单元的地址用两个元素来描述,即段地址和偏移地址。所以,如果“数据在21F60H内存单元中”,的说话有两种:1.) 数据存在内存2000: 1F60单元中;2.) 数据存在内在的2000段中的1F60单元中。 6. 段寄存器 8086CPU有4个段寄存器:CS,DS,SS,ES。 1.) CS和IP
CS和IP是8086CPU中两个最关键的寄存器,它们指针了CPU当前要读取指令的地址。CS为代码段寄存器,IP为指令指针寄存器,从名称上可以看出它们和指令的关系。
在8086PC机中,任意时刻,设CS中的内容为M,IP中的内容为N,8086CPU将从内存M * 16 + N单元开始,读取一条指令并执行。也可表述为:CPUCSIP指向的内容当作指令执行。 8086CPU工作过程:
1.)从CS:IP指向内在单元读取指令,读取的指令进入指令缓冲器;
2.)IP = IP + 所读取指令的长度,从而指向下一条指令;
3.)执行指令。转到团聚1.),重复这具过程 8086CPU 加电启动或复位后(CPU刚开始工作时)CS和IP被设置为CS = F000H,IP = FFFFH,即CPU是从内存FFFF0H单元中读取指令执行,FFFF0H单元中的指令是8086CPU开机后执行的第一条指令。 在这里,CS和IP为CPU提供了所要执行指令的地址。 在任何时候,CPU将CS、IP中的内容当作指令的段地址和偏移地址,用它们合成指令的物理地址,到内存中读取指令码,执行。如果说,内存中的一段信息被CPU执行过的话,那么,它所在的内存单元必然被CS:IP指向过。 2.) 修改CS、IP的指令 程序员能用指令读写的部件只有寄存器,并可以通过改变寄存器中的指令实现对CPU控制。而CPU中的指令是由CS,IP中的内容决定的,所以,通过修改CS, IP中的内容来控制CPU执行的目标指令。 8086CPU大部分寄存器的值,都可用mov指令来修改,mov指令也被称为传送指令。但mov指令却不能用于修改CS, IP的值,原因是8086CPU没有提供这样的功能。用于修改CS, IP的指令被称为转移指令,即:jmp指令。 若想同时修改CS, IP的内容,可用指令“jmp 段地址: 偏移地址”来完成,如:
jmp 2AE3:3, 执行后:CS = 2AE2H, IP = 0003H, CPU将从2AE33H处读取指令。
jmp 3:0B1B, 执行后:CS = 0003H, IP = 0B16H,CPU将从00B46H处读取指令。
jmp 段地址: 偏移地址”的指令功能是:用指令中给出的段地址修改CS, 偏移地址修改IP。 若想仅修改IP的内容,可用指令“jmp 某一合法寄存器” 完成,如:
jmp ax, 指令执行前:ax = 1000H, CS = 2000H, IP = 0003H
指令执行后:ax = 1000H, CS = 2000H, IP = 1000H jmp bx, 指令执行前:bx = 0B16H, CS = 2000H, IP = 0003H
指令执行后:ax = 0B16H, CS = 2000H, IP = 0B16H
指令“jmp 某一合法寄存器”的功能是:用寄存器中的值修改IP jmp ax, 相当于mov IP, ax 这样的指令。当然,前面已经说到mov指令是不能用于修改CS, IP的,这里只是类比说明。 如果有段代码需要CPU执行,就要让CS、IP指向这块代码所存储的内存地址的首地址。 7. 基于Windows下Debug 的使用
Debug是DOS,Windows的实模式(8086方式)程序的调试工具,使用它可查看CPU各种寄存器中的内容、内存的情况和机器码和跟踪程序的运行。

Debug常用命令:
1.)R命令查看/修改CPU寄存器内容;
2.)D命令查看内存中的内容;
3.)E命令修改内存中的内容;
4.)U命令将内存中的机器指令翻译成汇编指令(反汇编);
5.)T命令机器指令跟踪;
6.)A命令以汇编指令的格式在内存中写入一条机器指令;

1.)R命令格式:R {寄存器名} (注:{} 表参数为可选,下同)





以上执行了r,r ax,1111,r命令, r 先查看CPU寄存器中的内容; r ax 查看/修改(此时也可修改寄存器)寄存器ax中的内容; 1111 输入需修改的值 r 查看CPU寄存器中内容 2.)D命令格式:D {段地址: 偏移地址}

要查看内在10000H处的内容,先将这个地址表示为段地址:偏移地址的格式,可以是:1000:0,然后用“d 1000:0”列出在1000:0处的内容。 上面输出分3部分,中间部分是从指定的地址开始的128个内存单元的内容,用16进制的格式输出,每行输出从16的整数倍的地址开始,最多输出16个单元的内容。注意在每行的中间有一个‘-’,它将每行的输出分为两部分,这样便于查看。‘-’的左边是高段,右边是低段。 左边是每行的起始地址。 右边是每个内存单元中的数据对应可显示的ASCII码。 在使用“d 段地址: 偏移地址”后,再接着使用d命令,可列出以偏移量(前一条d 段地址: 偏移地址中的偏移量)为单元显示后面内存地址中的内容。如:

也可以查看指定内存地址范围内的内容“d 段地址: 起始偏移地址 结尾偏移地址”,如要查看1000:0 ~ 1000:9,命令为:d 1000:0 9:

如果想查看内在单元10000H中的内容,可以让“段地址: 偏移地址 ”都表示10000H这个物理地址,命令为:d 1000:0 0:

3.)E命令格式:E 起始地址 数据 数据 数据 … 如果要将内存1000:0 ~ 1000:9 单元中的内容改写为:0, 1, 2, 3, 4, 5, 6, 7, 8, 9,命令为:e 1000:0 0 1 2 3 4 5 6 7 8 9

当然也可一个一个地改写内存中的内容,如:

以上在输入e 1000:10后,会提示在"B0.”后输入你想修改的数据,此时空格,提示下一个内存单元想要输入的数据。如果还想继续输入,可继续空格。如果要跳过某个内存单元,可直接空格,跳到下一单元。 如果想对1000:0, 1000:2, 1000:4单元内写入数据1,2,3,对1000:1, 1000:3, 1000:5单元内写入字符'a', 'b', 'c',命令为:e 1000:0 1 'a' 2 'b' 3 'c':

如果想从1000: 0开始写入:1, 字符串"a+b", 2, 字符串"c++", 3, 字符串"IBM",命令为:e 1000:0 1 "a+b" 2 "c++" 3 "IBM":

4.)U命令格式:U 段地址 如果要查看e 1000:0 b8 01 00 b9 02 00 01 c8 这条指令翻译成汇编(反汇编)指令,可以用命令:U 1000:0

U命令的输出分为3部分:最左边的是机器指令的地址,中间是机器指令,右边是机器指令所对应的汇编指令。 5.)T命令格式:T {段地址: 偏移地址} 如果简单执行T命令,可执行CS: IP指向命令:

上图中,先是E命令从1000:0开始的内存单元里写入8个字节的机器码,再用R命令查看CPU中寄存器的状态,此时是CS = 1383, IP = 0100。接着再修改CS,IP的指向,使CS:IP 指向1000:0。再使用T命令跟踪前面的命令,执行后的AX中的内容被改写为1,IP改为IP + 3(mov ax, 0001的指令长度为3个字节),CS:IP指向下一指令。 6.)A命令格式:A {段地址:偏移地址}

A命令写入汇编指令时,在给出的起始地址后按ENTER键结束操作。 当然,你也可以直接使用A命令来给一直预定的地址(这个预定地址可以用R命令来查看)写入汇编指令,如:

以上部分内容参考:http://www.aogosoft.com/downpage.asp?mode=viewtext&id=66
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: