基础知识
组成
汇编指令
机器码的助记符,汇编语言的核心
mov ax,bx
伪指令
其他符号
存储器
指令和数据存放的地方
1000100111011000 -> 89D8H(数据)
1000100111011000 -> mov ax,bx(指令)
写汇编的时候数据不需要写末尾的 H
存储单元
存储器被划分成若干个存储单元,每个存储单一从 0 开始顺序编号,共 128 个,每个 1 Bety
读写
地址总线
地址总线能传送多少不同的信息,CPU 就能对多少存储单元进行寻址,即地址总线的宽度决定了 CPU 的寻址能力
如 10 根导线可以传送 个二进制数据,则地址总数为 个,而一个存储单元有
1B
,因此寻址能力1KB
数据总线
数据总线的宽度决定了 CPU 与外界的数据传送速度
如
8088CPU
有 8 根数据总线,宽度为 8,8086CPU
有 16 根数据总线
控制总线
地址空间
接口卡
CPU 不能直接控制外部设备,而只能控制外部设备扩展插槽上的接口卡,而接口卡能直接控制外部设备
各种存储器
通用寄存器
分别为AX``BX``CX``DX
8086CPU
的通用寄存器为 16 位,即2B
,用于存放一般数据 通用寄存器同时还具有特殊的功能:AX
主要用于存放数据BX
常用来存放访问存储器时的地址CX
常用于保存计算值,如在移位指令,循环和串处理指令中用作隐含的计数器DX
常用于数据传递
一个寄存器又可以分成两个独立的 8 位寄存器,如AX
可以分成AL
(低位) 和AH
(高位) 两个
字
汇编指令
赋值 mov
mov ax,18 ; 将 18 (实际上是 0018H) 送入寄存器 ax 中
mov ah,18 ; 将 18 送入寄存器 ah 中
; mov ah,D812 这样是错误的, 16 位不能送入 8 位寄存器中
mov ax,bx ; 将寄存器 bx 的数据送入寄存器 ax 中
mov ax,[0] ; 将内存单元“默认段地址(ds):0”的数据送入 ax
mov [0],ax ; 将ax的数据送入“默认段地址(ds):0”内存单元
加法 add
add ax,bx ; ax=ax+bx
mov al,C5
add al,93 ; 结果 C5H+93H=158H, 超过 8 位会截断为 al=58H, 不会进位到 ah
减法 sub
sub ax,bx ; ax=ax-bx
物理地址
有 20 根地址总线,其寻址范围为
是 16 位结构的 ,即 一次处理、传输、存放数据的能力最大为 16 位
内存地址在送入地址线时需要在 中暂时存放,因此只能使用两个 16 位地址合成 20 位地址
- 偏移地址(
EA
)有 16 位,因此仅用偏移地址寻址,最多有 个地址单元 不同的段地址(
SA
)和偏移地址能够表示相同的物理地址如
数据存在 单元中,则段地址最大为 (即偏移地址为 0),最小为 (即偏移地址为 ),但是由于 ,再除以 16 得 ,如果段地址为 明显不能获得物理地址 ,因此最小只能为
段寄存器
指令地址 CS:IP
CS
代码段寄存器,存放段地址IP
指令指针寄存器,存放偏移地址
CS:IP
所指向地址的内容被看作指令SS:SP
所指向地址被看作栈顶CPU
开机启动后,CS=FFFF``IP=0000
此处有一个跳转指令,去初始化BIOS
,初始化结束后,调用int 19h
进行操作系统引导,计算机此时被操作系统控制
指令跳转 jmp(修改CS/IP)
jmp 2AE3:3 ; 跳转到 2AE3:0003
jmp cs:ip
这只能在debug
里用,源程序中不可以这么写
mov bx,3
jmp bx ; 跳转到“ds:0003”
读取完指令后(即指令从内存中读取后放入CPU的指令缓存器中) IP 就会自增 如果读取到
jmp bx
则IP
会先增,然后在执行的时候被修改成bx
所指向的数据
mov ax,1000H
mov cs,ax ; 可行
mov cs,1000H ; 不可行
mov IP,1000H ; 不可行
DOSBox
常用命令
- R:查看、改变 CPU 寄存器的内容
r ds ; 查看 ds 的数据
- D:查看内存中的内容
d cs:0 ; 查看指令
d ds:0 ; 查看数据
d ss:0 ; 查看栈段数据
- E:改写内存中的内容
e ds:0 ; 向 ds:0 写入数据
- U:机器指令翻译成汇编指令
T:执行一条指令
当 T 执行的是修改栈段寄存器 的指令时,它的下一步指令也会跟着执行(即执行两条指令)
A:写入指令
- G:直接跳到某条指令
内存访问
DS [address]
mov bx, 1000
mov ds,bx
mov al,[0] ; 将 1000:0 的数据送入 al, [...] 里的值表示 IP(偏移地址)
寄存器存放默认段地址,可通过 MOV 指令修改 高级语言中数组第一个元素
a[0]
与ds:[0]
有相似之处
DS 不能直接送入数据
段寄存器只能通过寄存器或者内存单元中转
mov ax,1000
mov ds,ax
mov ds,[0] ; 段寄存器也可以接收内存单位的数据
mov ds,1000 ; 不可行
段寄存器相互不能传送数据
mov ds,cs ; 不可行
mov ds,ss ; 不可行
不能对段寄存器进行 和 操作
add ds,ax ; 不可行
add ax,ds ; 不可行
[…] 不能直接送入数据
mov [0],ds ; 可以把段寄存器的内容送入内存单位
mov [0],1000 ; 不可行
inc [0] ; 自增运算也不行
不能直接送入数据是因为 无法知道送入的数据是字型数据还是字节型数据,因此只要声明一下,还是可以直接送入的
mov word ptr [0],1000 ; 字型
mov byte ptr [0],10 ; 字节型
inc word ptr [0] ; 以字型方式自增, 可行
栈
以字为单位
栈地址 SS:SP
mov ax,0123
push ax
pop bx ;bx=0123
- 栈空间是需要自己分配的,但也可以使用默认的
- 一个栈变化范围最多为 ,即 的空间,如果不手动改变 ,一直进行 操作最后会形成一个环
- 高地址向低地址的方向入栈,并且入栈前先改变 SP,再送入数据
- 空栈
- 出栈不会删除原有的数据
- CPU 不会处理栈越界的问题,即如果越界了不会提示,会覆盖栈空间外的数据(可能存在覆盖重要数据的风险)
- 不可以直接向栈段寄存器 SS 直接送入数据,但可以向 SP 直接送入数据
栈实现逆序
mov ax,1000
mov ds,ax
mov ax,2000
mov ss,ax
mov sp,0010
push [0]
push [2]
push [4]
push [6]
push [8]
push [A]
push [C]
push [E]
mov ax,2000
mov ds,ax
mov ax,1000
mov ss,ax
mov sp,0000
pop [E]
pop [C]
pop [A]
pop [8]
pop [6]
pop [4]
pop [2]
pop [0]