内部总线
之前讨论的总线是CPU控制外部设备使用的总线,是将CPU和外部部件连接的。而CPU内部由寄存器,运算器,控制器等组成,由内部总线相连,内部总线负责连接CPU内部的部件。
通用寄存器
8086CPU寄存器都是16位的,一共14个,分别是AX,BX,CX,DX,SI,DI,SP,BP,IP,CS,SS,DS,ES,PSW。其中AX,BX,CX,DX四个寄存器通常存放一般性的数据,称为通用寄存器。
而且为了兼容上一代的8位寄存器,这四个寄存器可以拆开成两个8位的寄存器来使用。称为AH,AL,BH,BL,CH,CL,DH,DL。低八位(编号0-7)构成L寄存器,高八位构成H寄存器。
字
8086CPU可以处理以下两种数据
- 字节byte,8位
- 字word,连个字节,16位。分别称为高位字节和低位字节。
简单的汇编指令
| 指令 | 操作 | 高级语言 | | —- | —- | —- | | mov ax,18 | 将18存入AX寄存器 | AX=18 | | add ax,8 | 将AX寄存器中的数加8 | AX=AX+8 | | mov ax,bx | 将BX中的数据存入AX | AX=BX | | add ax,bx | 将AX中的数据和BX中的数据相加存入AX | AX=AX+BX |
汇编指令或寄存器名称不区分大小写。
注:
- AX寄存器当做两个8位寄存器al和ah使用的时候,CPU就把他们当做两个8位寄存器使用,而不会看成
是一个16未分开,即如果al进行加法运算C5+93=158,即add al,93,al会变成58,ax则是0058而不是0158。
- 16位除以8位,被除数放在AX中,除数可以由8位寄存器或者内存单元提供,结果的商放在AL中,余数放在AH中
- 32位除以16位,被除数的高16位放在DX中,低16位放在AX中,结果的商放在AX中,余数放在DX中
CPU位结构
16位结构的CPU指的是运算器一次最多处理16位数据,寄存器宽度16,寄存器和运算器之间通路也是16位。
16、32位或者64位等x位的CPU具有以下几方面特性:
- 运算器一次最多可以处理x位的数据
- 寄存器的最大宽度位x位
- 寄存器和运算器之间的数据通路位x位
CPU表示物理地址
8086CPU有20位地址总线,可以传送20位地址,达到1MB寻址能力。8086CPU又是16位结构,在内部一次性处理,传输,暂存的地址位16位。如果将地址从内部简单地发出,那么它只能送出16位地址,表现出寻址能力只有64KB。8086CPU采取在内部用两个16位地址合成的方法来形成一个20位的物理地址。
也就是说,如果物理总线宽度超过寄存器宽度,CPU寻址方法是两个寄存器输出一个地址,当地址总线宽度20的时候,图2.6。一个寄存器输出短地址,另一个输出偏移地址。然后通过地址加法器合并为一个20位的地址,然后通过内部总线送给控制电路,控制电路通过地址总线送给内存。
公式:物理地址=段地址x16+偏移地址(这里的x16其实就是左移四位,下图)
CPU访问内存时,用一个基础地址(段地址x16)和一个相对于基础地址的偏移地址相加,给出内存单元的物理地址。
虽然这么表示,但内存并没有被分为一段一段的,是CPU划分的段。段地址x16称为基础地址,所以我们可以根据需求把任意的基础地址加上不超过一个寄存器表示的最长(64KB)的偏移地址来表示地址。而且一个实际地址往往可以有各种不同的方法表示,通常我们表示21F60H这个地址通过下面方法:
- 2000:1F60
-
段寄存器与指令指针寄存器
8086CPU有四个段寄存器:CS,DS,SS,ES
CS
Code Segment, 用来和IP配合,实现执行流跳转。- CS:IP指示了当前要读取的指令的地址。
DS
Data Segment, 用来进行数据操作。
- [……]表示一个内存单元,以段寄存器DS中的数据为段地址,……为数据的偏移地址。
- DS:[address]表示某个数据的内存单元地址
SS
Stack Segment, 用来进行栈操作。
- SS:SP永远指向栈顶元素
段寄存器不支持直接赋值(硬件电路设计如此),如mov CS,100h之类的指令是不行的,只能从其他寄存器赋值过来,如:
mov ax,100h
mov cs,ax
除此之外,IP寄存器称为指令指针寄存器,所以任意时刻可以读取从CSx16+IP单元开始,读取一条指令执行。也就是说,CPU将IP指向的内容当做指令执行。
图2.11,CPU执行一段指令。另外,8086CPU开机时CS被置为FFFFH,IP被置为0000H,也就是说刚开机的第一条指令从FFFF0H开始读取执行。
CPU将CS:IP指向的内存中的内容当做指令,一条指令被执行了,那一定被CS:IP指向过。
修改CS,IP
CS和IP是8086CPU中两个最关键的寄存器,它们指示了CPU当前要读取指令的地址。CS为代码段寄存器,IP为指令指针寄存器,从名称上我们可以看出它们和指令的关系。在8086PC机中,任意时刻,设CS中的内容为M,IP中的内容为N,8086CPU将从内存的Mx16+N单元开始,读取一条指令并执行。
在8086CPU加电启动或复位后(即CPU刚开始工作时)CS和IP被设置成CS=FFFF,IP=0000,即在8086PC机刚启动时,CPU从内存FFFF0单元中读取指令执行,FFFF0单元中的指令时8086PC机开机后执行的第一条指令。
要修改寄存器的内容,可以用mov指令,但是CS/IP的值不能用mov直接设置。8086CPU为CS/IP提供了另外的指令来改变它们的值。能够改变CS/IP的内容的指令被统称为转移指令。
jmp指令用法:
jmp 段地址:偏移地址
同时修改CS和IP的值。如jmp 2AE3:3
结果CS=2AE3H IP=0003Hjmp 某一合法寄存器
只修改IP的值。如jmp ax
,将IP的值置为AX中的值(AX不变)。如jmp AX
执行前AX=1000,CS=2000,IP=003。执行后AX=1000,CS=2000,IP=1000小结
8086CPU有四个段寄存器,CS是用来存放指令的段地址的段寄存器
IP用来存放指令的偏移地址
CS:IP指向的内容在任意时刻会被当做指令执行
使用转移指令修改CS和IP的内容实验
Debug命令:
R
:查看,改变CPU寄存器内容- 直接-r查看寄存器内容
- -r 寄存器名,改变寄存器内容
D
:查看内存中内容- -d直接查看
- -d 段地址:偏移地址 查看固定地址开始的内容
- -d 段地址:偏移地址 结尾偏移地址 查看指定范围内存
E
:改写内存中内容- -e 起始地址 数据 数据 数据 …
- 提问方式修改 -e 段地址:偏移地址 从这个地址开始一个一个改,空格下一个,回车结束
- 也可以写入字符 ‘a’
U
:将内存中的机器指令翻译成汇编指令- -u 段地址:偏移地址
T
:执行一条机器指令- -t 执行cs:ip指向的命令
A
:以汇编指令格式在内存中写入一条机器指令- -a 段地址:偏移地址 从这个地址开始一行一行的写入汇编语句