寄存器
CPU是由运算器,控制器,和各种寄存器组成的。CPU通过外部总线与主板上的设备产生联系,而CPU通过内部总线实现CPU内部各个期间之间的联系。
简单的来说在CPU中:
- 运算器进行信息处理
- 寄存器用来储存各种信息
- 控制器控制各种器件进行工作
- 内部总线连接各种器件,在它们之间进行数据传送
- 程序员可以通过改变各种寄存器中的内容来实现对CPU的控制
通用寄存器
8086CPU中所有寄存器都是16位的,可以存储两个字节(1个字)的数据。AX、BX、CX、DX这四个寄存器一般用来存放一般性的数据,因此被称为通用寄存器。因为8086CPU上一代CPU使用的寄存器是8位的,所以为了保证兼容,可以把十六位的寄存器分成两个8位寄存器来使用。
比如
- AX可以分为AH、AL;
- BX可以分为BH、BL;
- CX可以分为CH、CL;
- DX可以分为DH、DL;
比如这是将AX分为两个8位寄存器来使用,其中高8位用AH表示,低8位用AL来表示。
字在寄存器中的存储
出于对兼容性的考虑,8086CPU可以一次性处理连着大小的数据------字节或字。
- 字节:记为byte,一个字节由8个bite(位)组成,可以存放在8位寄存器中
- 字:记为word,一个字由两个字节组成,可以由16位寄存器保存。一个字可以分为两个字节,高位字节和低位字节。
几条汇编指令
汇编指令 | 控制CPU完成的操作 | 用高级语言的语法描述 |
---|---|---|
mov ax,18 | 将18送入寄存器AX | AX=18 |
mov ah,78 | 将78送入寄存器ah中 | AH=78 |
add ax,8 | 将ax中的值与8的值的和放入寄存器ax中 | AX=AX+8 |
mov ax,bx | 将寄存器中bx的值放入寄存器ax中 | AX = BX |
add ax,bx | 将寄存器bx和寄存器ax中的值相加结果放入ax中 | AX=AX+BX |
值得注意的是在汇编语言中并不区别大小写所以MOV AX,18与mov ax,18并没有什么区别。
几点需要注意的
- 如果8位寄存器相加结果放入8位寄存器中,如果这两个数相加产生了进位,8位寄存器只会存入低8位字节。
- 在进行数据传送或者运算时还要求两个存储器的位数相同。
物理地址
我们知道CPU访问内存单元时需要给出内存单元的地址,因为内存单元的组成的存储空间是线性一维的,每个存储单元多有一个唯一的地址,这个地址被我们称为物理地址。
8086是16位结构的CPU,16位结构的CPU有什么特点呢?
16位结构的CPU
- 运算器一次最多可以处理16位的数据
- 寄存器的最大宽度为16位
- 寄存器和运算器之间的通路为16位
8086CPU给出物理地址的方法
8086CPU的地址总线是20位,故可以传送20位的地址,达到1MB的寻址能力,但是8086CPU又是16位结构,在内部只能一次传送16位的数据。如果只是单纯得将地址从内部简单发出,那么它只能发出16位的地址,表现出的寻址能力只有64KB。8086CPU采用一种在内部用两个16位地址合成的方法来形成一个20位的物理的地址
当8086CPU要读写内存时候:
- CPU中的相关部件提供两个16位的地址,一个被称为段地址,另一个被称为偏移地址;
- 段地址和偏移地址通过内部总线传入一个称为地址加法器的部件;
- 地址加法器将两个16位地址合成一个20位的物理地址;
- 地址加法器通过内部总线将20位物理地址送入输入输出控制电路
- 输入输出控制电路将20位物理地址送上地址总线;
- 20位物理地址被地址总线传送到存储器
地址加法器采用的算法是物理地址 = 段地址 * 16 +偏移地址
物理地址 = 段地址 * 16 +偏移地址的本质
接下来我将解释一下这个等式的本质,其实我们可以把存储空间人为分为几个小的存储段,段地址*16其实我们可以把它叫做基础地址,基础地址就是我们人为分的存储段的起始地址,偏移地址就是在基础地址下移动的位数罢了。所以根据我们这个定义,我们人为划分的段的启示地址一定是16的倍数,而因为偏移地址是16位的,所以一个段的长度最长为64KB。
段寄存器
CS、DS、SS这些存储器又被叫做段寄存器,这些寄存器是用来存放段地址的。
CS和IP
CS段寄存器是用来提供段地址的,IP寄存器是用来存放偏移地址的,CPU中的地址加法器就是用CS和IP寄存器中的值来合成物理地址的。
CPU执行指令的步骤:
- 在8086CPU家电启动或复位后CS和IP分别被设置为FFFFH和0000H所以FFFF0H地址的存储单元是8086CPU执行的第一条指令。
- 从CS:IP指向的内存单元读取指令,读取的指令进入指令缓冲器中;
- ip = ip+所读指令的长度,从而指向下一条指令;
- 执行指令,转到步骤1,重复这个过程。
在汇编语言中不能通过mov给CS和IP输入值,所以8086CPU准备了jmp指令来修改CS、IP的值。
jmp指令有以下两种用法
jmp 段地址:偏移地址 这个用法会直接修改CS中值和IP中的值
jmp 某一合法寄存器指令的功能是用寄存器中的值修改ip
比如 jmp ax在含义上相当于 mov ip,ax。
接下来我将介绍以下debug的使用
debug
什么是debug,debug是实模式程序的调试工具,使用它可以查看CPU各种寄存器中的内容、内存的情况和在机器码级跟踪程序的运行。
我们常用的debug的功能
- 用debug的R命令我们可以查看cpu中各种寄存器中的内容
- 用debug的D命令我们可以查看内存中的内容
- 用debug的E命令我们可以改写内存中的内容
- 用debug的u命令我们可以查看内存中的机器码翻译成的汇编指令
- 用debug的T命令我们可以依次执行CS:IP指向的的汇编指令
- 用Debug的A命令我们可以以汇编指令的格式在内存中写入一条机器指令。
R命令
r寄存器名,可以直接修改该寄存器中的内容,比如rcs,便可以修改cs段寄存器中的内容
D命令
d命令会直接列出从指定地址开始的128个字节的内容
D命令的格式比较多,如果直接使用d命令,那么将会直接查看debug预设的地址处的内容。
如果使用 d 段地址:偏移地址将列出从该物理地址所指向的存储单元的内容开始的128个字节的内容
如果使用 d 段地址:起始偏移地址 结尾偏移地址,那么只会列出从起始指向地址的存储单元的内容到结尾指向地址存储单元的内容。
E命令
我们可以通过 e 段地址:偏移地址 数据 数据 数据 数据 修改从指向的地址处开始的数据,
或可以通过e 段地址:偏移地址,采用提问的方式修改数据。我们可以通过输入值按空格完成对数据的修改,如果不想修改了直接按ENTER键就可以退出修改数据。
u命令
通过 u 段地址:偏移地址可以查看从指向地址开始的汇编指令
t命令
直接使用t就可以运行cs:ip指向的指令了
a命令
使用a 段地址:偏移地址,我们便可从指向地址处开始通过汇编指令写入程序,在显示地址后直接按回车便可以退出输入。