本文为汇编语言考试复习整理 →_→
寄存器
通用寄存器(General Purpose Registers)均可以拆成2个8位寄存器使用,如AX寄存器可以拆成AL(低位)、AH(高位)使用。
Types | Registers | Full Name | Function |
---|---|---|---|
General Purpose Registers | AX | Accumulator Register | 存储数据;乘除法;中断指令;不能用作偏移地址索引 |
BX | Base Register | 偏移地址索引(默认段地址为DS) | |
CX | Counter Register | 循环计数;不能用作偏移地址索引 | |
DX | Data Register | 存储数据;乘除法;不能用作偏移地址索引 | |
Segment Registers | CS | Code Segment | 代码段的段地址 |
DS | Data Segment | 数据段的段地址 | |
SS | Stack Segment | 栈段的段地址 | |
ES | Extra Segment | 额外段的段地址 | |
Special Purpose Registers | SP | Stack Pointer | 栈段的偏移地址;不能用作偏移地址索引 |
BP | Base Pointer | 偏移地址索引(默认段地址为SS) | |
IP | Instruction Pointer | 代码段的偏移地址 | |
SI | Source Index | 串传送指令源地址;源偏移地址索引 | |
DI | Destination Index | 串传送指令目的地址;目的偏移地址索引 | |
Flag Register | PSW | Program Status Word | 存储相关指令的执行结果 |
更多内容可参考 https://www.geeksforgeeks.org/types-of-registers-in-8086-microprocessor/
标志寄存器

PSW | Full Name | 1 |
---|---|---|
ZF | Zero Flag | 计算结果为0 |
PF | Parity Flag | 计算结果二进制有偶数个1 |
SF | Sign Flag | 计算结果为负 |
CF | Carry Flag | 当作无符号数计算,结果存在进位溢出 |
OF | Overflow Flag | 当作有符号数计算,结果存在溢出 |
AF | Auxiliary Carry Flag | 计算过程是否存在进位 |
DF | Directional Flag | 串传送方向从高到低 |
IF | Interrupt Flag | 接受中断 |
TF | Trap Flag | 单步执行 |
更多内容可参考 https://www.geeksforgeeks.org/flag-register-8086-microprocessor/
寻址
16位的寄存器,20位的地址总线。CPU 向地址总线发送物理地址前需先计算出来,计算方式如下:
物理地址(20位) = 段地址 x 10H + 偏移地址
所以,可能存在不同段地址和偏移地址指向一个物理地址的情况。
内存单元
在 DEBUG.EXE 中,内存单元按照低地址到高地址的方式显示,每两个紧邻的数表示一个字节(Byte),每行显示16个字节。

上图中,如果DS寄存器(Data Segment)为076C,则指令 mov ax,[0]
将使AX寄存器被赋值为十六进制的C88C。(C8在高地址,所以在高位;8C在低地址,所以在低位)
此外,内存单元存储地址时,段地址存储于高地址,偏移地址存储于低地址。
指令语法
1. mov ax,0f500h
解释:将十六进制的f500(最后的 h
表示十六进制;数值的第一位是字母 f
所以需要加上 0
)赋值给AX寄存器
段寄存器(CS、DS、SS、ES)不能直接赋值数据,需要通过寄存器(段寄存器和IP除外)赋值
内存单元可以通过寄存器或者数据赋值,不能使用 mov 内存单元地址,内存单元地址
赋值,下面两种均是可以的。
mov ds:[0],ax ; ax已经指明是word类型,无需加上word ptr
mov word ptr ds:[0],33h ; 需要指定word ptr或者byte ptr
2. add ax,2
解释:将十进制的2加给AX寄存器,也可以对内存单元使用,如 add word ptr es:[0],33h
;相关的指令有 sub ax,2
,使AX寄存器减去十进制的2
3. inc ax
解释:AX寄存器加1,也可以对内存单元使用,如 inc word ptr es:[0]
;相关的指令有 dec ax
,使AX寄存器减1
4. push ax
解释:将AX寄存器(或者内存单元)的值入栈
栈顶为SS:SP,满足先入后出原则,入栈SP变小,出栈SP变大;使用时需要先声明栈段(stack segment),栈段完全由程序员控制,没有保护机制。此外, push
和 pop
时,SP只能加2或者减2。
指令 | 解释 |
---|---|
push ax |
1. sub sp,2 2. mov ss:[sp],ax
|
pop ax |
1. mov ax,ss:[sp] 2. add sp,2
|
5. loop s
解释:同一个代码段(段内短转移)往前跳转到s标记处循环
- CX减1,并判断是否为0
- 如果CX为0,则不跳转继续往下执行代码;如果CX大于0,则跳转到s标记循环
6. and al,11011111b
解释:将AL值的二进制与 11011111b
做与运算,功能上将AL转为大写字符
and | 0 | 1 |
0 | 0 | 0 |
1 | 0 | 1 |
相关的指令有 or al,00100000b
,它是将AL值的二进制与 00100000b
做或运算,功能上将AL转为小写字符
or | 0 | 1 |
0 | 0 | 1 |
1 | 1 | 1 |
7. db 'unIX'
解释:在内存中定义字节型(byte)数据,等效于 db 75H,6EH,49H,58H
, 75H,6EH,49H,58H
为 unIX
的16进制ASCII码
相类似的还有dw(define word)、dd(define double word),均是编译器识别的伪指令
8. div bx
解释:BX为除数,被除数为AX(低位)和DX(高位)构成的数,商存放于AX中,余数存放于DX中
除数 | 被除数 | 商 | 余数 |
---|---|---|---|
8位 | AX | AL | AH |
16位 | AX(低位)、DX(高位) | AX | DX |
相关的指令有 mul bx
,这里BX为乘数,被乘数为AX,积为AX(低位)和DX(高位)构成的数
乘数 | 被乘数 | 积 |
---|---|---|
8位 | AL | AX |
16位 | AX | AX(低位)、DX(高位) |
; 应用举例
div reg ; 8位或者16位reg
div 内存单元地址 ; 需要加上 byte ptr / word ptr
div word ptr es:[0]
div byte ptr [bx + si + 8] ; ds:[bx + si + 8]
mul reg ; 8位或者16位reg
mul 内存单元地址 ; 需要加上 byte ptr / word ptr
mul word ptr es:[0]
mul byte ptr [bx + si + 8] ; ds:[bx + si + 8]
9. db 200 dup (0)
解释:定义200个字节的 0
, dup
(duplication)同样也是编译器识别的伪指令
10. mov si,offset s
解释:操作符 offset
由编译器识别,值为标记 s
处相对代码起始位置的偏移量,通常用于串传送
11. jmp short s
解释:CS和IP由于其特殊性,不能直接通过赋值改变,jmp指令登场! jmp short s
跳转到标号s处执行代码,是段内短转移,转移范围为 -128~127
(段内转移只改变IP)
指令 | 解释 | 类别 |
---|---|---|
jmp short s |
跳转到标号s处 | 段内短转移( -128~127 ) |
jmp near ptr s |
跳转到标号s处 | 段内近转移( -32768~32767 ) |
jmp ax |
将AX的值赋给IP | 段内近转移( -32768~32767 ) |
jmp far ptr s |
跳转到标号s处 | 段间远转移(改变CS和IP) |
jmp word ptr 内存单元地址 |
内存单元的值赋给IP | 段内近转移( -32768~32767 ) |
jmp dword ptr 内存单元地址 |
内存单元低地址赋给IP,高地址赋给CS | 段间远转移(改变CS和IP) |
12. jcxz s
解释:当CX为0时,跳转到标号s处,否则往下执行;属于有条件转移指令,短转移,对IP的修改范围为 -128~127
13. call s
解释:将call下一条指令1的地址压入栈中,然后跳转到标号s处
搭档 | 解释 | 指令 | 解释 |
---|---|---|---|
ret |
1. pop ip
|
call s |
1. push ip 2. jmp near ptr s
|
call 16位reg |
1. push ip 2. jmp 16位reg
|
||
call word ptr 内存单元地址 |
1. push ip 2. jmp word ptr 内存单元地址
|
||
retf |
1. pop ip 2. pop cs
|
call far ptr s |
1. push cs 2. push ip 3. jmp far ptr s
|
call dword ptr 内存单元地址 |
1. push cs 2. push ip 3. jmp dword ptr 内存单元地址
|
14. adc ax,bx
解释:带进位加法,前面指令对标志寄存器中CF的影响会加到这里,等效于 (ax)+(bx)+CF
相关的指令还有 sbb ax,bx
,带进位减法
add al,bl
adc ah,bh
; 等效于 add ax,bx
sub al,bl
sbb ah,bh
; 等效于 sub ax,bx
15. cmp ax,bx
解释:用AX减BX,但不保存结果,只影响标志寄存器,一般和je等条件转移搭配使用
无符号条件转移有:je、jne、jb、jnb、ja、jna;有符号条件转移有:jg、jng、jl、jnl;更多内容可参考:http://marin.jb.free.fr/jumps/
; 应用示例
cmp bl,11
jb s
inc ax
s: inc si
loop k
...
16. pushf
解释:标志寄存器压栈
相关指令 popf
从栈中取值赋给标志寄存器
17. rep movsb
解释:串传送指令, movsb
是按照byte传送; movsw
是按照word传送
指令 | 解释 |
---|---|
movsb |
1. ((es)*16+(di))=((ds)*16+(si)) 2. 如果df=0( cld ),则 inc si ,inc di ;如果df=1( std ),则 dec si , dec di
|
rep movsb |
s:movsb loop s (重复次数由CX决定) |
串传送步骤:
- 设置DS:SI和ES:DI
- 设置传送方向,cld(低到高)、std(高到低)
- 设置传送长度CX
-
rep movsb
或者rep movsw
18. int 21h
解释:21h号中断,对应中断向量表 0:21h*4
位置(这里存储了21h中断例程的段地址 0:21h*4+2
和偏移地址 0:21h*4
),再执行中断例程,一般中断程序中会有 iret
返回
指令 | 解释 |
---|---|
int 21h |
1. 取得中断类型码N(如21h) 2. pushf 3. TF=0,IF=0 4. push cs , push ip 5. (IP)=(4\*N),(CS)=(4\*N+2) |
iret |
1. pop ip 2. pop cs 3. popf
|
报错指南
-
[idata]
单独表示编译器会报错,可以使用ds:[idata]
,或者先mov bx,idata
再用[bx]
表示(idata
即普通数据,如33H) - 不能对两个内存单元地址直接操作,如
mov 内存单元地址,内存单元地址
- 包含多段(code segment、data segment、stack segment等)的程序必需加入代码开始标号,最后
end 标号
,否则编译器默认第一段开始为代码段 - 地址如果用16进制表示,结尾需要加上H
- 内存单元与数据的操作(
mov
、add
、and
等),需要指明word ptr
或者byte ptr
-
CPU执行指令的步骤是:1. 从CS:IP指向的内存单元读取指令进入指令缓冲器;2. IP指向下一条指令;3. 执行缓冲器中的指令 ↩
Leave a comment