1. 寄存器以及数据存储
寄存器,是在cpu内部用于存储数据或者指令的单元。
1.1 CPU的组成
-
运算器进行信息处理;
-
寄存器进行信息存储;
-
控制器协调各种器件进行工作;
-
内部总线实现CPU内各个器件之间的联系;
1.2 寄存器是CPU内部的信息存储单元
8086CPU有14个寄存器:
- 通用寄存器:AX、BX、CX、DX;
- 变址寄存器:SI、DI
- 指针寄存器:SP、BP
- 指令指针寄存器: IP
- 段寄存器:CS、SS、DS、ES
- 标志寄存器:PSW
共性
8086CPU所有的寄存器都是16位的
,可以存放两个字节
;
1.3 通用寄存器
一个16位寄存器存储一个16位的数据,
-
汇编程序中,默认的使用10进制表示,如果数据后面有H,则代表是十六进制;
-
. 而在debug 环境中,默认的是16进制表示;
最大值?
2
16
−
1
2^{16}-1
216−1
在AX中存储18D:
— 12H
— 10010B
再例:在AX中存储20000D
20000D
— 4E20H
— 0100111000100000B
1.4寄存器的兼容
8086上一代CPU中的寄存器都是8位的,如何保证程序的兼容性?
- 通用寄存器均可以分为两个独立的8位寄存器使用.
细化
; AX可以分为AH和AL
; BX可以分为BH和BL
; CX可以分为CH和CL
; DX可以分为DH和DL
1.5 "字”在寄存器中的存储
8086是16位CPU
; 8086的字长(word size)为16bit
;
一个字(word)可以存在一个16位寄存器中:
; 这个字的高位字节存在这个寄存器的高8位寄存器
; 这个字的低位字节存在这个寄存器的低8位寄存器
而在内存中存储的时候,低位字节的数据存放在低地址内存单元中,高位字节存放在高地址内存单元中
2. mov, add指令
注:汇编指令不区分大小写
2.1学习汇编指令——用中学
2.2 写出汇编指令执行的结果(1)
设原AX、BX中的值均为0000H,
注意, 最后一步中加的结果,导致结果溢出
,
2.3写出汇编指令执行的结果(2)
注意, 最后一步中加的结果,导致结果溢出
,
在使用 8位寄存器,相加时, 产生的溢出进位,不能保存到高8位的寄存器;
因为相加时,使用的是8位寄存器,当存在进位溢出时,只能丢弃不能进位到高8位的寄存器,
只有当使用的16位寄存器相加时,低8位产生的溢出,才可以进位到高8位的寄存器中
。
即,若执行add ax, 93H,AX结果为0158H
3. 确定物理地址的方法
3.1 物理地址
-
CPU访问内存单元时要给出内存单元的地址。
-
所有的内存单元构成的存储空间是一个一维的线性空间。
-
每一个内存单元在这个空间中都有唯一的地址,这个唯一的地址称为物理地址。
- 事实
- 8086有20位地址总线,可传送20位地址,寻址能力为1M。
- 8086是16位结构的CPU;
- 运算器一次最多可以处理16位的数据,寄存器的最大宽度为16位。
- 在8086内部处理的、传输、暂存的地址也是16位,寻址能力也只有64KB!
地址总线的宽度和cpu中寄存器的宽度不一样
,
问题:8086如何处理在寻址空间上的这个矛盾?!
3.2 8086CPU给出物理地址的方法
8086CPU的解决方法
用两个16位地址(段地址、偏移地址) ,合成一个20位的物理地址
。
地址加法器合成物理地址的方法;
物理地址=段地址×16+偏移地址
而乘16,代表了十六进制数,左移一位;
8086CPU访问地址为123C8H的内存单元:
3.3 “段地址×16+偏移地址=物理地址”的本质含义
要解决的问题:
用两个16位的地址(段地址、偏移地址),相加得到一个20位的物理地址.
本质含义:
CPU在访问内存时,用一个基础地址(段地址×16)和一个相对于基础地址的偏移地址相加,给出内存单元的物理地址。
4.内存的分段表示法
4.1 用分段的方式管理内存
8086CPU用“(段地址×16)+偏移地址=物理地址”的方式给出内存单元的物理地址.
所有硬件设备的地址,都会映射到内存中,不同的硬件设备地址对应到内存单元中不同的物理地址;
- 内存并没有分段,段的划分来自于CPU!!!
4.2 同一段内存, 多种分段方案
(1)段地址×16 必然是 16的倍数,所以一个段的起始地址也一定是16的倍数;
(2)偏移地址为16位,16 位地址的寻址能力为 64K,所以一个段的长度最大为64K。
左边图中, 起始地址( 基础地址) 为10000H;
段地址为1000H, 大小为100H;
右边图中: 起始地址( 基础地址 ) 为10000H和10080H,
段地址为1000H和1008H, 大小均为80H
4.3用不同的段地址和偏移地址形成同一个物理地址
偏移地址16位,变化范围为0~FFFFH,用偏移地址最多寻址64KB.
给定段地址2000H,用偏移地址寻址的范围是:20000H~2FFFFFH,共64K;
在8086PC机中存储单元地址的表示方法:
数据在21F60H内存单元中,段地址是2000H,说法
(a)数据存在内存2000:1F60单元中;
(b)数据存在内存的2000H段中的1F60H单元中
段地址: 使用4种专用寄存器来存放,四种不同类型的段地址
4中类型的寄存器:
cs: 代码段寄存器;
DS: 数据段寄存器;
SS: 栈段寄存器;
ES: 扩展寄存器;
偏移地址可以用多种方法提供——8086丰富的取址方式。
5. Debug 的使用
5.1Debug是什么
Debug是DOS系统中的著名的调试程序,也可以运行在windows系统实模式下。
使用Debug程序,可以查看CPU各种寄存器中的内容、内存的情况,并且在机器指令级跟踪程序的运行!
Debug就是传奇!
5.2 Debug能做什么
- 用R命令查看、改变CPU寄存器的内容;
: 用D命令查看内存中的内容
: 用E命令改变内存中的内容
: 用U命令将内存中的机器指令翻译成汇编指令
: 用A命令以汇编指令的格式在内存中写入机器指令
: 用T命令执行机器指令
启动Debug, 在DOS提示符下输入命令:debug
5.2.1 用R命令查看、 改变CPU寄存器的内容
- R - 查看寄存器内容
- R 寄存器名 - 改变指定寄存器内容
5.2.2 用D命令查看内存中的内容
D 列出预设地址内存处的128个字节的内容;
D 段地址:偏移地址 , 列出内存中指定地址处的内容;
D 段地址:偏移地址, 结尾偏移地址 - 列出内存中指定地址范围内的内容;
5.2.3 用E命令改变内存中的内容
E 段地址:偏移地址 数据1 数据2 …
E 段地址:偏移地址
; 逐个询问式修改
; 空格 - 接受,继续
; 回车 - 结束
5.2.4 用U命令将内存中的机器指令翻译成汇编指令
有汇编指令
mov ax, 0123H
mov bx, 0003H
mov ax, bx
add ax, bx
对应的机器码为
B8 23 01
BB 03 00
89 D8
01 D8
e 地址 数据 - 写入
d 地址 - 查看
u 地址 - 查看代码
5.2.5 用A命令以汇编指令的格式在内存中写入机器指令
有汇编指令
mov ax, 0123H
mov bx, 0003H
mov ax, bx
add ax, bx
对应的机器码为
B8 23 01
BB 03 00
89 D8
01 D8
a 地址 - 写入汇编指令
d 地址 - 查看数据
u 地址 - 查看代码
5.2.6 用T命令执行机器指令
t - 执行CS:IP处的指令
mov ax, 0123H
mov bx, 0003H
mov ax, bx
add ax, bx
5.2.7 用Q命令退出Debug
q - 退出Debug
6. cs,ip 与代码段
内存单元中的内容, 究竟用作数据,还是用作指令
:
取决于cpu如何使用,
如果是
CS:ip
, 则表示指向的内存单元中的内容用作指令,
因为cs:
代表了code segmentation 代码段,
而如果是
ds:
则代表的是, data segmentation 数据段, 则表明内存单元中的内容,用作数据。
6.1 两个关键的寄存器
指令的执行,是通过 cs 和ip来找到内存单元中需要执行的指令;
专用寄存器名称 | 作用 |
---|---|
CS | 代码段寄存器 |
IP | 指令指针寄存器 |
CS:IP:
CPU将内存中CS:IP指向的内容当作指令执行
6.2 在CS和IP指示下代码的执行
8086CPU当前状态:CS中内容为2000H,IP中内容为0000H
内存20000H~20009H处存放着可执行的机器代码
6.3 8086PC读取和执行指令演示
8086PC工作过程的简要描述:
(1)从CS:IP指向内存单元读取指令,读取的指令进入指令缓冲器;
(2)IP = IP + 所读取指令的长度,从而指向下一条指令;
(3)执行指令。 转到步骤(1),重复这个过程
6.4 指令读取和执行的实证演示-Debug
用debug程序执行下面的代码
mov ax, 0123H
mov bx, 0003H
mov ax, bx
add ax, bx
a 地址 - 写入汇编指令
u 地址 - 查看代码
t - 执行CS:IP处代码
问:内存中有数据 B8 23 01 BB 03 00 89 D8 01 D8,
究竟用作一般数据,还是用作指令?
答:CPU将CS:IP指向的内存单元中的内容看作指令
7. jmp 指令
7.1 修改CS、 IP的指令
事实:执行何处的指令,取决于CS:IP;
- 应用:可以通过改变CS、IP中的内容,来控制CPU要执行的目标指令
问题:如何改变CS、IP的值?
方法1:Debug 中的 R 命令可以改变寄存器的值——rcs, rip
但 Debug是调试手段,并非程序方式!
方法2:用指令修改
对于cpu中的专用寄存器而言(四种段地址寄存器和ip寄存器),不可以使用立即数 赋值的形式
cs等专用寄存器,虽然可以通过其他通用寄存器来赋值,但是不属于常规操作,不常用
ip的数值,只能是cpu自身改变,不可以通过赋值改变
注意: 8086CPU不提供通过赋值的方式,对CS和IP修改的指令!
方法3:转移指令 jmp
7.2 转移指令 jmp
- 同时修改CS、IP的内容
jmp 段地址:偏移地址
jmp 2AE3:3
jmp 3:0B16
功能:用指令中给出的段地址修改CS,偏移地址修改IP
- 仅修改IP的内容
jmp 某一合法寄存器
jmp ax (类似于 mov IP, ax)
jmp bx
功能:用寄存器中的值修改IP。
7.3 问题分析
从20000H开始,执行的序列是:
(1)mov ax,6622
(2)jmp 1000:3
(3)mov ax,0000
(4)mov bx,ax
(5)jmp bx
(6)mov ax,0123H
(7)转到第(3)步执行
这里注意到,两字节的数据在存放时,低字节的数据存放在内存单元中的低地址, 高字节的数据存放在内存单元中的高地址
对应书籍章节
对应的章节内容: