基础汇编
基础汇编
一、基础知识
基础:
注意事项:
- 小端模式:高地址高字节,低地址低字节
- 数据不能以字母开头,所以:0FFFFH
- 安全空间:0:200H - 0:2FFH
二、寄存器
1 普通寄存器
通用寄存器(AX,BX,CX,DX( 分高低位:AH,AL)):
- AX:累加寄存器。
- BX:基址寄存器,用于内存寻址。(
ds:[bx]
)- CX:计数寄存器,用于 loop 循环。
- DX:数据寄存器。
段寄存器(CS,DS,SS,ES(IP,SP)):
特点:数据不能直接送入段寄存器,需要用寄存器送入段寄存器。
CS:代码段寄存器,IP:指令指针寄存器,
CS:IP(CS*10H + IP)
寻址。DS:数据段寄存器,[p] 的地址寻址默认是
DS:[ p ]
。SS:堆栈段寄存器,SP:堆栈指针寄存器,
SS:SP
指向栈顶元素。(SS被修改后下一条指令也会被执行。所以mov ss,ax; mov sp,10; 会一次性被执行)ES:附加段寄存器。
其他:
- SI:源变址寄存器(无法分高低位)
- DI:目的变址寄存器(无法分高低位)
- BP:基址指针寄存器(ss:bp 指向内存)
- PSW:标志寄存器(如下)
2 标志寄存器位
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
/ | / | / | / | OF | DF | IF | TF | SF | ZF | / | AF | / | PF | / | CF |
标志寄存器PSW是一个16为的寄存器。它反映了CPU运算的状态特征并且存放某些控制标志。8086使用了16位中的9位,包括6个状态标志位和3个控制标志位。
标志寄存器:
- CF(Carry flag):进位标志位。无符号计算在最高位产生了进位或借位时,CF=1;反之,CF=0。
ZF(Zero flag):零标志位。当运算结果全零时,ZF=1;反之,ZF=0。
SF(Sign flag):符号标志位。当运算结果为正数,即结果的最高位为0时,SF=0;反之,即结果的最高位为1时,SF=1。
OF(Over flow flag):溢出标志位。带符号数运算结果超出了补码所能表示的范围,OF=1;反之,OF=0。OF=最高位进位与次高位进位的异或。
PF(Parity flag):奇偶标志。算术逻辑运算的结果中低8位“1”的个数为偶数个时,PF=1;为奇数时,PF=0。
AF(Auxiliary carry flag):辅助进位标志。在运算过程中,第四位向第五位有进位或借位时,AF=1;反之,AF=0。
CF判断否是溢出的方法是:进行二进制运算时,最高位的进位与次高位的进位值进行异或运算若运算结果为1则表示溢出OF=1 ,否则OF=0。
溢出三条原则:
- 同号相加和异号相减才会发生溢出。
- 同号相加结果的符号与参与运算的符号不同就溢出。
- 异号相减结果的符号位与被减数的符号位不同就产生溢出。
另外还有三个控制标志位用来控制CPU的操作,可以由程序进行置位和复位:
TF(Trap Flag):跟踪标志。当 TF=1 时,CPU进入单步工作方式;当 TF=0 时,正常执行程序。
IF(Interrupt flag):中断标志位。当 IF=1 时,CPU可以响应外部可屏蔽中断请求;当 IF=0 时,CPU不响应外部可屏蔽中断请求。但 IF 对不可屏蔽中断或内部中断没有影响。
DF(Direction flag):方向标志。当 DF=0 时,si,di递增;当 DF=1 时,si,di递减。
标志位 | 值1 | 值0 |
---|---|---|
CF(Carry flag) | CY(1) carry | NC(0) no carry |
ZF(Zero flag) | ZR(1) zero | NZ(0) no zero |
SF(Sign flag) | NG(1) negative | PL(0) plus |
OF(Over flow flag) | OV(1) overflow | NV(0) no overflow |
PF(Parity flag) | PE(1) parity even | PO(0) parity odd |
AF(Auxiliary carry flag) | AC(1) auxiliary carry | NA(0) no auxiliary |
TF(Trap Flag) | 1 | 0 |
IF(Interrupt flag) | EI(1) enable interrupt | DI(0) disable interrupt |
DF(Direction flag) | DN(1) down | UP(0) up |
3 内存寻址
;默认: |
三、程序编译
1 普通汇编指令
注:() 表示寄存器值
1.1 移动指令
; 将 (bx) 送入 ax |
1.2 运算指令
; (ax) = (ax) + (bx) |
1.3 逻辑指令
; (al) = (al) && <num> |
1.4 处理机控制指令
sti ;设置IF=1 |
2 复杂汇编指令
2.1 div
内存寻址可以用 byte ptr 或 word ptr 指明大小。
除数:8b 或 16b,在 [] 或 reg 中。
被除数:除数8b,被除数16b,放在ax;除数16b,被除数32b,dx放高16b,ax放低16b。
商:除数8b,商在 al 中,余数在 ah 中;除数16b,商在 ax中,余数在 dx 中。
格式:div [bx] / reg
2.2 mul
内存寻址可以用 byte ptr 或 word ptr 指明大小。
乘数:都 8b,一个在 al,一个是 reg 或 [];都 16b,一个在 ax,一个是 reg 或 []。
结果:8b 在 ax,16b 高位 dx,低位 ax。
2.3 cmp
; 比较 |
2.4 串操作
; 把 1B / 2B数据从 ds:si 送到 es:di,次数依照 cx |
3 Debug
debug file.exe:进入debug
R:看寄存器:
-r
:查看CPU寄存器内容-r ax
:改寄存器值D:看机器码:
-d cs:ip
:查看指定地址的机器码-d + -d
:连续使用 -d 自动查看下一段地址-d cs:ip ip
:查看指定 ip 段的地址E:改机器码:
- -
e cs:ip
:改机器码-e cs:ip 'a' / "a+b"
:写入字符或字符串U:反汇编:
-u cs:ip
:反编译(机器码变汇编语言)T:执行指令:
-t
:执行一条指令A:写汇编:
-a cs:ip
:写入汇编语句other:
-g ip
:一次性执行到 ip 处-p
:int 21H要用 p 命令执行-quit
:退出debug
4 程序产生
编译过程:
- 编译:masm file[.asm](非 asm 需要后缀,最后加上 ; 直接一次性编译,不用填信息)
- 链接:link file[.obj](非 obj 需要后缀,可加 ; )
数据段和代码段之间会存在一个 PSP(256 B)
; 代码内容 |
; 定义大小 |
5 特殊内存空间
彩色缓冲区:
B8000H ~ BFFFFH 的内存空间会显示在显示器上。
通常是 B80000H ~ B8F9FH 中的 4000 个字节显示在显示器上。
- 一行 80 个字符 160 个字节,一页 25 行。
- 一个字低位是内容,高位是颜色,含义从(7(BL)闪烁,654(RGB)背景,3(I)高亮,210(RGB)前景)
四、转移指令
1 跳转
定义:可以修改 ip ,或同时修改 cs 和 ip 的指令称为跳转指令。
8086CPU分类:无条件转移指令(jmp),条件转移指令,循环指令(如:loop),过程,中断。
分类:
- 段内转移:只修改 ip,例:jmp ax。
- 段间转移:修改 cs 和 ip。例:jmp 1000:0。
- 短转移:ip 变化 -128 ~ 127
- 近转移:ip 变化 -32768 ~ 32767
jmp:jmp 的机器码记录的不是 jmp 的目的地址,而是 jmp 的下一条指令距离 jmp 终点的距离。
; 跳转指令 |
; jmp跳转 |
2 call 和 ret
call label / reg / word ptr ds:[bx]
:
(sp) = (sp) - 2
((ss)*16 + (sp)) = (ip)
(ip) = (ip) + 16位位移
ret
:
(ip) = ((ss)*16 + (sp))
(sp) = (sp) + 2
call far ptr / dword ptr ds:[bx]
:
(sp) = (sp) - 2
((ss)*16 + (sp)) = (cs)
(sp) = (sp) - 2
((ss)*16 + (sp)) = (ip)
(cs) = label.cs
(ip) = label.ip
retf
:
(ip) = ((ss)*16 + (sp))
(sp) = (sp) + 2
(cs) = ((ss)*16 + (sp))
(sp) = (sp) + 2
五、中断
1 内中断
中断向量表:
8086PC机,中断向量表指定放在内存地址 0 处,从内存 0000:0000 到 0000:03FF 的 1024 个单元存放中断向量表,放着256个中断源所对应的中断处理程序的入口。
一般情况下,0000:0200到0000:02FF的256个字节空间所对应的中断向量表项都是空的。
安装中断
设置中断
; do0 |
2 int指令
int指令(int n,n 为中断向量码):
- 取中断类型码 n
- 标志寄存器入栈,IF = 0,TF = 0
- CS,IP 入栈
- IP = ( n 4 ),CS = ( n 4 + 2 )
int 0H:除法中断,
0:[0*4]和0:[0*4+2]
int 9H:向键盘缓冲区写入,键盘输入到达60H端口后同时引发的中断。
; int 10H:屏幕输出中断 |
; int 13H:磁盘读写(软盘结构:面——磁道——扇区——字节) |
; int 16H:键盘读入 |
; int 21H:调用子程序 |
3 端口
端口访问:in 和 out 读写数据只能用 al 和 ax。al 是 8位,ax 是 16位。
CMOS RAM芯片:
该芯片有一个实时时钟和一个有128个存储单元的RAM存储器。(早期的计算机为64个字节)
128个字节的RAM中,内部实时钟占用0~0DH单元来保存时间信息,其余大部分单元保存系统配置信息,供系统启动时BIOS程序读取。
70H为端口地址,存放要访问的CMOS RAM单元的地址。
71H为数据端口,存放从选定的CMOS RAM单元中读取的数据。
时间存放是BCD码存放(BCD码4b,所以8b即可存两位数),时间存放单元如下:
存放单元 | 秒:0 | 分:2 | 时:4 | 日:7 | 月:8 | 年:9 |
---|---|---|---|---|---|---|
; 端口 |
;读2号单元数据 |
4 外中断
外中断信息:
CPU通过端口和外部设备进行联系。
键盘输入的扫描码在60h端口产生,同时引发int 9中断(向键盘缓冲区写入)。
在BIOS键盘缓冲区中,一个键盘用一个字存储,高位放扫描码,低位放字符码。键盘缓冲区最多可以存15个键盘输入。
按下一个键时产生的扫描码称为通码,松开一个键产生的扫描码称为断码。断码=通码+80H。
键盘输入:
5 直接定址表
利用内存空间做个字典
6 BIOS键盘输入和磁盘读写
自启动:
- CPU一加电初始化 (CS)=0FFFFH,(IP)=0。该处有一个跳转执行,CPU执行后会去执行BIOS中的硬件检测和初始化程序。
- 硬件检测完后会调用 int 19H 进行操作系统引导。
- 键盘读取:int 16H(缓冲区写入:int 9H)
- 磁盘读写:int 13H