BCD码

  • 二进制编码的十进制数:一位十进制数用4位二进制编码来表示

  • 8086支持压缩BCD码和非压缩BCD码的调整运算

    真值 8 64
    二进制编码 08H 40H
    压缩BCD码 08H 64H
    非压缩BCD码 08H 0604H

压缩BCD码加、减调整指令

image-20240731173047934

  • 使用DAA或DAS指令前,应先执行以AL为目的操作数的加法或减法指令

非压缩BCD码加、减调整指令

image-20240731172224489

  • 使用AAA或AAS指令前应先执行以AL为目的操作数的加法或减法指令
  • AAA和AAS指令在调整中产生了进位或借位,则AH要加上进位或减去借位,同时CF=AF=1,否则CF=AF=0;它们对其他标志无定义

非压缩BCD码乘、除调整指令

image-20240731174214645

  • AAM指令跟在字节乘MUL之后,将乘积调整位非压缩BCD码
  • AAD指令跟在字节除DIV之前,先将非压缩BCD码的被除数调整为二进制数
  • AAM和AAD指令根据结果设置SF、ZF和PF,但对OF、CF和AF无定义
1
2
3
4
5
6
7
8
9
mov al,19h ;bcd压缩码 19+1==>20
inc al ;16运算结果调整为10进制的运算结果 1a==>20
daa
;das ;调整减法
;非bcd压缩码
mov ax,0109h
inc ax
aaa
;aas

image-20240731175027448

控制转移类指令

  • 控制转移类指令用于实现分支、循环、过程等程序结构后,是仅次于传送指令的最常用指令

    重点掌握:JMP/JCC/LOOP CALL/RET

    INT n/IRET 常用系统功能调用

    一般了解: LOOPZ/LOOPNZ INTO

无条件转移指令

1
JMP label ;程序转向label标号指定的地址
  • 只要执行无条件转移指令JMP,就使程序转到指定的目标地址处,从目标地址处开始执行那里的指令
  • 操作数label是要转移到的目标地址(目的地址、转移地址)
  • JMP指令分为4种类型:
    • 段内转移、直接寻址
    • 段内转移、间接寻址
    • 段间转移、直接寻址
    • 段间转移、间接寻址

目标地址的寻址方式

  • 直接寻址方式(用标号表达)
    • 转移地址像立即数一样,直接在指令的机器代码中,解释直接寻址方式
  • 间接寻址方式(用寄存器或存储器操作数表达)
    • 转移地址在寄存器或主存单元中,就是通过寄存器或存储器的间接寻址方式

目标地址的范围:段内

  • 段内转移——近转移(near)
    • 在当前代码段64KB范围内转移(-32KB~+32KB范围)
    • 不需要更改CS段地址,只要改变IP偏移地址
  • 段内转移——短转移(short)
    • 转移范围可以用一个字节表达,在段内-128~+127范围的转移

段内转移、直接寻址

1
JMP label ;IP<-IP+位移量(实际为相对寻址)
  • 位移量是紧接着JMP指令后的那条指令的偏移地址,到目标指令的偏移地址的地址位移
  • 当向地址增大方向转移时,位移量为正;向地址减小方向转移时,位移量为负

image-20240801193253626

段内转移、间接寻址

1
JMP r16/m16 ;IP<-r16/m16
  • 将一个16位寄存器或主存字单元内容送入IP寄存器,作为新的指令指针,但不修改CS寄存器的内容

image-20240801193517811

目标地址的范围:段间

  • 段间转移——远转移(far)
    • 从当前代码段跳转到另一个代码段,可以在1MB范围
    • 需要更改CS段地址和IP偏移地址
    • 目标地址必须用一个32位数表达,叫做32位远指针,它就是逻辑地址
  • 实际编程时,汇编程序会根据目标地址的距离,自动处理成短转移、近转移或远转移
  • 程序员可用操作符short、near ptr或far ptr强制

段间转移、直接寻址

1
JMP far ptr label ;IP<-label的偏移地址 CS<-label的段地址
  • 将标号所在段的段地址作为新的CS值,标号在该段内的偏移地址作为新的IP值;这样,程序跳转到新的代码段执行

image-20240801203004029

1
2
3
4
5
6
7
8
9
10
11
12
13
MyData segment             ;数据段
TABLE1 db 03,04,05,06
string db "Hello World!",0dh,0ah,'$';换行
;path db "C:\1.txt",0
NUM1 dw 0ffffh
MyData ends

;控制转移类指令
LOOP1:
mov dx,offset string
mov ah,09h
int 21h
jmp LOOP1

运行成功后会重复打印Hello World!

image-20240801204618562

1
2
3
4
5
6
7
8
9
10
11
12
13
14
;控制转移类指令
;1.短转移
jmp short LOOP1
;2.近转移
jmp near ptr LOOP1
mov dx,offset string
mov ah,09h
int 21h

LOOP1:
;算法运算类指令
mov al,19h ;bcd压缩码 19+1==>20
inc al ;16运算结果调整为10进制的运算结果 1a==>20
daa

0A和07代表跳转的偏移(7+2+A=13,9+3+7=13)

short的偏移为2个字节

near的偏移为4个字节

image-20240801205545960

1
2
3
4
5
LOOP1:
mov dx,offset string
mov ah,09h
int 21h
jmp near ptr LOOP1

F6为10的补码,E+3-10+7

image-20240801210135059

1
jmp LOOP1 ;伪指令

若省略short或near,则系统自动根据位移选择跳转方式

image-20240801210725308

1
2
3
4
5
6
7
8
9
MyCode2 segment
TEST1:
mov dx,offset string
mov ah,09h
int 21h
MyCode2 ends

;段间转移
jmp far ptr TEST1

077F即为MyCode2的基地址

image-20240801210915571

成功跳转到MyCode2

image-20240801211307230

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
MyCode2 segment
TEST1:
mov dx,offset string
mov ah,09h
int 21h
jmp far ptr end1
MyCode2 ends

MyCode segment ;代码段
start: ;告诉编译器代码从此处开始
mov ax,MyData ;获取段基址
mov ds,ax ;将段基址送入寄存器
mov es,ax

;控制转移类指令
;1.短转移
; jmp short LOOP1
;2.近转移
; jmp near ptr LOOP1

;段间转移
jmp far ptr TEST1

LOOP1:
mov dx,offset string
mov ah,09h
int 21h
jmp LOOP1 ;伪指令

end1:
;算法运算类指令
mov al,19h ;bcd压缩码 19+1==>20

成功跳转回MyCode1

image-20240801211604925

相对寻址方式

  • Jcc指令的操作数label是一个标号
    • 一个8位位移量,表示Jcc指令后的那条指令的偏移地址,到目标指令的偏移地址的地址位移
    • 8位位移量是相对当前IP的,且距当前IP地址-128~+127个单元的范围之内,属于段内短距离转移
    • Jcc目标地址就采用这种相对寻址方式
  • Jcc指令为2个字节,条件不满足时的顺序执行就是当前指令偏移指针IP加2
1
2
3
4
5
6
7
8
9
10
mov cx,10
LOOP1:
mov dx,offset string
mov ah,09h
int 21h
dec cx
;jmp LOOP1 ;伪指令
end1:
;循环10次 条件跳转 jcc
jnz LOOP1

每完成一次循环CX会自动减一

image-20240801213339598

当CX为0时ZF为1,退出循环

image-20240801213549183

1
2
3
4
5
6
7
mov ax,1 ;if(ax==1) ax=0
cmp ax,1
jnz LABEL2
mov ax,0
LABEL2:
;算法运算类指令
mov al,19h ;bcd压缩码 19+1==>20

ZF为1,说明AX==1,则不执行跳转,给AX赋值为0

image-20240801214123912

条件转移指令中的条件cc

image-20240801214303421

  • 等于E(equal)
  • 有符号:大于G(greater),小于L(less),大于等于jge,小于等于jle
  • 无符号:大于A(above),小于B(below),大于等于jae ,小于等于jbe

判断单个标志位状态

  • 这组指令单独判断5个状态标志之一
    • JZ/JE和JNZ/JNE:利用零标志ZF,判断结果是否为零(或相等)
    • JS和JNS:利用符号标志SF,判断结果是正是负
    • JO和JNO:利用溢出标志OF,判断结果是否产生溢出
    • JP/JPE和JNP/JPO:利用奇偶标志PF,判断结果中“1”的个数是偶是奇
    • JC/JB/JNAE和JNC/JNC/JAE:利用进位标志CF,判断结果是否进位或借位

比较无符号数高低

  • 无符号数的大小用高(Above)低(Below)表示
  • 利用CF确定高低、利用ZF标志确定相等(Equal)
  • 两数的高低分成4种关系:
    • 低于(不高于等于):JB(JNAE)
    • 不低于(高于等于):JNB(JAE)
    • 低于等于(不高于):JBE(JNA)
    • 不低于等于(高于):JNBE(JA)