汇编
寄存器部分。
寄存器
- 一个典型的CPU由运算器、控制器、寄存器等器件组成
- 这些器件靠内部总线相连,之前所说的地址总线、数据总线、控制总线相对CPU内部而言,是外部总线
- 内部总线实现CPU内部各个器件之间的联系,外部总线实现CPU和主板上其他器件的联系
CPU内部器件
- 运算器负责信息处理
- 寄存器负责信息存储
- 控制器控制各个器件进行工作
- 内部总线连接各个内部器件,在它们之间进行数据传送
- 我们可以通过改变寄存器中的内容来实现对CPU的控制
通用寄存器
- 8086CPU的所有寄存器都是16位的,可以存放两个字节
- AX,BX,CX,DC这4个寄存器通常用来存放一般性的数据,称为通用寄存器
- 为了保证兼容性,AX,BX,CX,DX这4个寄存器都可以分为两个可独立使用的8位寄存器来使用
- AX可分为AH,AL
- BX可分为BH,BL
- CX可分为CH,CL
- DX可分为DH,DL
- 比如AX,低8位构成了AL,高8位构成了AH
字和字节的存储
- 一个字节(byte)8个位,可以存在8位寄存器中
- 一个字(word)两个字节,这两个字节可分别称为这个字的高位字节和低位字节,一个字可以存在16位寄存器中,而高位字节存在高8位寄存器,低位字节存在低8位寄存器
汇编指令
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中
物理地址
- CPU访问内存单元时,要给出内存单元的地址,所有的内存单元构成的存储空间是一个一维的线性空间
- 每一个内存单元在这个空间中都有唯一的地址,这个唯一的地址被称为物理地址
- CPU通过地址总线送入寄存器的,必须是一个内存单元的物理地址
- 在CPU向地址总线发出物理地址之前,必须要在内部先形成这个物理地址
- 不同的CPU有不同的形成物理地址的方式
16位结构的CPU
- 运算器一次最多可以处理16位的数据
- 寄存器的最大宽度为16位
- 寄存器和运算器之间的通路为16位
8086给出物理地址的方法
概述
- 8086CPU有20根地址总线,可以传送20位地址,达到1MB的寻址能力
- 8086是16位结构,在内部一次处理、传输、暂时存储的地址为16位
- 从8086的内部结构看,它只能发出16位的地址,表现出的寻址能力只有64KB
具体
- 8086CPU采用一种在内部用两个16位的地址来合成一个20位的物理地址的方法
- CPU中的相关部件提供两个16位的地址
- 一个称为段地址
- 一个称为偏移地址
- 段地址和偏移地址通过内部总线送入一个称为地址加法器的部件
- 地址加法器将两个16位的地址合成为一个20位的物理地址
- 地址加法器通过内部总线将20位物理地址送入输入输出控制电路
- 输入输出控制电路将20位物理地址送上地址总线
- 20位物理地址被地址总线传送到存储器
地址加法器算法
- 物理地址=段地址x16+偏移地址
其他
- 二进制的数据左移N位,相当于该数据乘以2的N次方
- X进制的数据左移1位,相当于该数据乘以X
算法含义
- CPU在访问内存时,用一个基础地址(段地址x16),和一个相对于基础地址上的偏移地址相加,给出内存单元的物理地址
- 基础地址+偏移地址=物理地址
- 不直接给出物理地址的原因,是可能不具备一次性容纳物理地址的位数的能力,因而必须根据现有条件进行运算
段的概念
- 段地址中“段”的概念可能会使人误以为内存被划分成为了一个一个的段,每一个段都有一个段地址
- 其实,内存并没有分段
- 段的划分,来自于CPU
- 由于8086CPU采用“段地址x16+偏移地址=物理地址”的方法给出内存单元的物理地址,使得我们可以采用分段的方法管理内存
- 编程时可以根据需要,将若干地址连续的内存单元看作一个段,用段地址x16定位段的起始地址,用偏移地址定位段中的内存单元
- 段地址x16必然是16的倍数,所以一个段的其实地址也一定是16的倍数
- 偏移地址为16位,16位地址的寻址能力为64KB,所以一个段的长度最大为64KB
- CPU可以根据不同的段地址和偏移地址形成同一个物理地址
段寄存器
- 8086CPU在访问内存时,要由相关部件提供内存单元的段地址和偏移地址,送到地址加法器合成物理地址
- 这个相关部件就是8086CPU的段寄存器
- CS
- DS
- SS
- ES
CS和IP
- CS和IP是8086CPU中两个最关键的寄存器
- CS为代码段寄存器
- IP为指令指针寄存器
- 在8086CPU中,任意时刻,设CS内容为M,IP内容为N,8086CPU将会从内存单元Mx16+N的单元开始,读取一条指令并执行
- 换句话,8086CPU在任意时刻,都将CS:IP指向的内容当作指令执行
- CPU工作过程概述
- 从CS、IP寄存器拿到段地址和偏移地址
- 送到地址加法器得到物理地址
- 将物理地址送入输入输出控制电路
- 输入输出控制电路将物理地址送到地址总线
- 从对应内存物理地址单元开始的位置存放的机器指令,通过数据总线被送到输入输出控制电路
- 输入输出控制电路将机器指令送入指令缓存器,同时IP的值增加指令的长度
- 执行控制器从指令缓存器中拿到指令后执行
- 对应的通用寄存器的内容相应更新
- 再次循环过程
- 在8086CPU中,加电启动或复位后,CS和IP分别被重置
- CS:FFFFH
- IP:0000H
- 也就是说,在8086机器刚启动的时候,CPU从FFFF0H内存单元中读取指令执行
- FFFF0H单元中的指令是8086CPU启动后的第一条指令
- 需要注意的问题
- 在内存中,存放的都是二进制数据,因而在某种程度上,指令和信息没用任何区别
- CPU如何区分指令和信息?
- CPU将CS:IP中的内容当作指令的段地址和偏移地址,用它们合成的物理地址到内存中读取指令码,然后执行
修改CS和IP的指令
- 在CPU中,程序员能够用指令读写的部件,只有寄存器。
- 换句话说,程序员可以通过改变寄存器中的内容来实现对CPU的控制
- 而,CPU从何处执行指令是由CS:IP寄存器的内容决定的
- 换句话说,程序员可以通过改变CS:IP中内容来控制CPU执行目标指令
- 如何更改CS:IP中的内容?
- 8086CPU大部分寄存器的值,都可以使用mov指令来改变
- mov指令被称为传送指令
- 但是,mov指令不能用于改变CS、IP的内容,8086CPU没用提供这样的功能
- 8086CPU为CS、IP提供了另外的指令来改变它们的值,而能够改变CS、IP内容的指令被统称为转移指令
- jmp可以修改CS、IP的内容
jmp 2AE3:3
、jmp 3:0B16
jmp 某一合法寄存器
、用寄存器中的值修改IP
代码段
背景
- 对于8086机器,在编程时,我们可以根据需要,将一组内存单元定义为一个段
- 这个段的长度为N,N<=64KB
- 段的起始地址为16的倍数
代码段
- 我们可以将长度为M,M<=64KB的一组代码,存在一组地址连续,起始地址为16的倍数的内存单元中
- 我们可以认为,这段地址是用来存放代码的,从而定义了一个代码段
- 代码段中的指令如何被执行呢?
- CPU只认被CS:IP寄存器指向所定义的代码段中的第一条指令的首地址
DOSBox
启动debug
- 打开dosbox
mount c D:\AsmTools
D:\AsmTools
是存放debug.exe的地方
c:
debug
debug命令
- 命令
r
查看寄存器内容 - 命令
r ax
将根据冒号后面的输入改变寄存器ax的内容 - 命令
d
查看内存中的内容 - 命令
e
改写内存中的内容e 073f:0010 54
:把对应字符改成T
- 命令
u
将内存中的机器指令翻译成汇编指令 - 命令
t
执行一条机器指令 - 命令
a
将以汇编指令的格式在内存中写入一条机器指令
本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!