Transcript Document

现代微机原理与接口技术(第3版)
第3章 80x86汇编语言程序设计(下)
1
http://www.njyangqs.com/
3.5 分支结构程序设计
现代微机原理与接口技术(第3版)
分支结构是指计算机根据实际情况或条件,作出判断
和选择,转而执行不同的程序段的一种程序结构。
条件
Y
程序段
2
N
Y
程序段A
条件
N
程序段B
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
多路分支结构
根据某个控制字的各“位”状态实行多路转移
多路条件测试
程序段1
3
程序段2
……
程序段n
http://www.njyangqs.com/
3.5.1无条件转移指令 JMP
1、段内转移
格式1:JMP SHORT OPR
操作1:IP<--(IP)+disp8
现代微机原理与接口技术(第3版)
;段内相对短转移
说明:转移范围-128字节至+127字节,操作数OPR为段内某个标号。
段内相对短转移示例
指令JMP SHORT ADDT 存放在CS:0200H 中,
标号ADDT对于IP指针的偏移量为1DH,
则转移地址为0202H+001DH=021FH
JMP SHORT ADDT
0200 E8
…
ADDT: MOV AL, 40H
ADD AL, BL
4
1
2
1D
+1DH
021F B0
0220 1D
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
格式2:JMP OPR
JMP NEAR PTR OPR ;段内相对近转移
操作2:IP<--(IP)+disp16
说明:转移范围-32KB至+32KB, 操作数OPR为段内
某个标号。
格式3:JMP WORD PTR OPR ;段内间接转移
操作3:IP<--(OPR)
说明:OPR是基址/变址寄存器或存储器操作数。
5
段内间接转移示例
ADDRESS DW 2000H ;定义转移地址
...
LEA SI, ADDRESS
;偏移量-->SI
...
JMP WORD PTR[SI]
;转移到CS:2000
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
2、段间转移
格式4:JMP FAR PTR OPR
操作4:IP<--OAopr
CS<--(CS)opr
段间直接转移示例
;代码段C1
……
JMP FAR PTR NEXT
……
;代码段C2
……
NEXT: MOV AL,10H
…
6
;段间直接转移
C1段
EA
50
02
00
20
C2段
NEXT
OP码
新IP=0250H
新CS=2000H
20000H
20250H
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
格式5:JMP DWORD PTR OPR ;段间间接转移
操作5:IP<--((DS)*16+OPR)
CS<--((DS)*16+OPR+2)
段间间接转移示例
JMP DWORD PTR [4000H]
设 (DS)=1000H
(14000H)=0010H (14002H)=5000H
执行后
(CS)=5000H (IP)=0010H
7
http://www.njyangqs.com/
3.5.2 条件转移指令
现代微机原理与接口技术(第3版)
格式:J条件 标号
操作:测试条件,若满足,则跳转到标号处执行,
即 IP<--(IP)+disp8 ;
否则,执行后续指令
说明:根据上一条指令所设置的条件码判别测试条件
转移范围在-128到+127字节
8
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
条件转移指令(1)
操作符
功能
JC
进位标志为1转移
JNC
进位标志为0转移
JZ/JE
等于0/相等转移
JNZ/JNE
不等于0/不相等转移
JS
符号标志为1转移
JNS
符号标志为0转移
JO
溢出转移
JNO
无溢出转移
JP/JPE
偶状态转移
JNP/JPO
奇状态转移
JCXZ
CX=0转移
JECXZ
ECX=0转移
9
测试条件
CF=1
CF=0
ZF=1
ZF=0
SF=1
SF=0
OF=1
OF=0
PF=1
PF=0
CX=0
ECX=0
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
条件转移指令(2) A-B
比较情况
A>B
A>=B
A<B
A<=B
10
无符号数
指令
判断条件
JA
ZF=0,CF=0
JNBE
JAE
ZF=1或
JNB
CF=0
JB
ZF=0,CF=1
JNAE
JBE
ZF=1或
JNA
CF=1
有符号数
指令
判断条件
JG
SF=OF
JNLE
且 ZF=0
JGE
SF=OF
JNL
或ZF=1
JL
SF<>OF
JNGE
且ZF=0
JLE
SF<>OF
JNG
或ZF=1
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
条件转移指令示例1
将X中十六进制的ASCII码转换成其所对应的数值,
存放到HEX中。如‘A’应转换为10。
注意ASCII中‘0’~‘9’是30H~39H,’A’~’F’是41H~46H
MOV AH, X
CMP AH, 39H
JBE NEXT
SUB AH, 7
NEXT: SUB AH, 30H
MOV HEX, AH
11
;≤39H则转
;是‘A’--’F’,减7
;减30H
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
条件转移指令示例2
CMP AX, 0FFFFH
Y
JLE P3
AX≤(-1)
CMP AX,1
N
JL P2
MOV AX, 1
N
Y
AX<1
JMP DONE
P2:
MOV AX, 0
JMP DONE
AX<--1
AX<--0
P3:
MOV AX,-1
DONE:
AX<--(-1)
如果条件转移目标地址超出-128~+127的范围怎么办?
12
http://www.njyangqs.com/
3.5.3 分支结构程序设计
现代微机原理与接口技术(第3版)
1、比较/转移
利用比较和条件转移指令实现两路分支。
比较结果记录在某些标志位中,条件转移指令
根据约定的条件进行对照,满足条件时转移,不满
足条件时不转移。
2、跳转表转移
利用跳转表实现多路分支。
比较/转移指令可嵌套,但程序结构复杂,
跳转表可使程序结构清晰。
教材上的例子请看P99中的例3.18和例3.19,上
机实现例3.18程序。
13
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
有一个首地址为ARRAY的N字数组,将其中正数
的个数放在DI中,0的个数放在SI中,负数个数
放在AX中
注意:负数个数=N-DI-SI
14
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
MOV CX, N
MOV BX, 0
;初始化
MOV DI, BX
; 正数个数计数器初始化
MOV SI, BX
; 0的个数计数器初始化
AGAIN:CMP WORRD PTR ARRAY[BX], 0
;数组当前元素与0比较
JLE LEEQ
;小于等于0转移
INC DI
;正数计数
JMP NEXT
LEEQ: JL NEXT
;小于0转移
INC SI
;0计数
NEXT: ADD BX, 2
;数组表指针指向下一元素
DEC CX
JNZ AGAIN
MOV AX, N
;负数个数=N-DI-SI
SUB AX, DI
SUB AX, SI
15
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
设字节单元N1、N2中存放无符号数
(1)若两个均是偶数,则分别加1后送D1 、D2中
(2)若两个均是奇数,则直接送D1 、D2中
(3)若一个是奇数,一个是偶数,则把奇数送D1,偶数
送D2中
AL<--(N1),AH<--(N2)
注意:根据条件
偶
,当N1是奇数时
奇
(AL)0=0
,无论N2是奇数
偶
奇
还是偶数,都只
(AH)0=0
需直接送D1、D2
AL<--(AL)+1
AH<--(AH)+1
(AL)
(AH)
D1<--(AL),D2<--(AH)
16
http://www.njyangqs.com/
程序如下:
MOV AL, N1
MOV AH, N2
TEST AL, 01H
JNE ENDO
TEST AH, 01H
JNE L1
INC AL
INC AH
JMP ENDO
L1:
XCHG AL, AH
ENDO: MOV D1, AL
MOV D2, AH
现代微机原理与接口技术(第3版)
;测试 N1的奇偶
;N1为奇数
;测试 N2的奇偶
;N2是奇数,转移
;两个均是偶数
;N1是偶数, N2是奇数
;存放结果
转上页
17
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
利用跳转表实现多路分支
跳转表是在某一内存区域顺序排列的一组有规律的入
口地址。
如是段内分支,每个地址占两个单元(IP的值)
如是段间分支,每个地址占4个单元(CS:IP的值)
TABLE
SUB1
TABLE
SUB1
IP
IP
IP SUB2
CS
IP
SUB3
IP
SUB2
CS
段内转移
18
段间转移
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
根据AL中哪一位为1(从低位到高位)把程序转移到8
个不同的程序分支去
.DATA
TABLE DW
DW
DW
DW
DW
DW
DW
DW
19
.CODE
ROUTINE_1
ROUTINE_2
ROUTINE_3
ROUTINE_4
ROUTINE_5
ROUTINE_6
ROUTINE_7
ROUTINE_8
……
ROUTINE_1: MOV AX,0
……
ROUTINE_2: CMP AL, 3
……
……
ROUTINE_8: CLI
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
用变址寻址方式
CMP AL, 0
JE
DONE
MOV SI, 0
L:
SHR AL, 1
JNB NOT_YET ; CF=0或ZF=1跳转
JMP TABLE[SI]
NOT_YET: JZ DONE
ADD SI, TYPE TABLE ;Type Table=2
JMP L
DONE:
……
20
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
在附加段中有一个从小到大排序的无符号数字数组,
其首地址在DI中,数组的第一个单元存放数组长度。
要求在数组中查找(AX),如找到,CF=0,并在SI中给
出该元素在数组中的偏移地址;如未找到,CF=1。
算法:在R数组中查找K,采用折半查找法
(1) LOW1, HIGHN;
(2) 若LOW>HIGH,则查找失败,置CF=1,退出程序。
否则,计算中点:MID(LOW+HIGH)/2;
(3) K与R[MID]比较。若=R[MID],则查找成功,程序
结束;
若K<R[MID]则转(4);若K>R[MID],则转(5);
(4) HIGHMID-1,转(2);
(5) LOWMID+1,转(2)。
21
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
CMP AX, ES:[DI+2] ;与第一个数比较
JA CHK_LAST ;(AX)>(ES:[DI+2]) 转
LEA SI, ES:[DI+2]
JE EXIT ;相等,找到,就是第一个数
STC
; 小于第一个数,失败
JMP EXIT
CHK_LAST:MOV SI, ES:[DI] ;取数组长度
SHL SI, 1
; 长度*2(DW型)
ADD SI, DI
CMP AX, ES:[SI] ; 与最后的数比较
JB SEARCH
; 小于则转
JE EXIT
; 相等则结束
STC
; 大于最后一个,失败
JMP EXIT
22
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
SEARCH: MOV LOW_IDX, 1 ; 给LOW赋初值
MOV BX, ES:[DI]
; 取数组长度
MOV HIGH_IDX, BX ; 给HIGH赋初值
MOV BX, DI
; BX中放首地址
MID:
MOV CX, LOW_IDX
MOV DX, HIGH_IDX
CMP CX, DX
JA NO_MATCH ; LOW>HIGH,失败
ADD CX, DX
SHR CX, 1
; 折半
MOV SI, CX
SHL SI, 1
; *2 (DW型)
COMPARE:CMP AX, ES:[BX+SI] ; 与中间数比较
JE EXIT
; 相等,找到
23
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
JA HIGHER ; 大于中间数,转
DEC CX
MOV HIGH_IDX, CX ; 调整查找区间到
前半部分
JMP MID
HIGHER:
INC CX
MOV LOW_IDX, CX ; 调整查找区间到
后半部分
JMP MID
NO_MATCH: STC
EXIT:
……
24
http://www.njyangqs.com/
3.6 循环结构程序设计
现代微机原理与接口技术(第3版)
任务需要重复执行某一程序段,这种情况采用循环结
构来实现。
初始化
循环体
初始化
控制部分
N
Y
修改部分
循环体
N
控制部分
修改部分
Y
25
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
3.6.1 循环指令
格式:指令码 标号; (CX中存放循环次数)
操作符
操
作
功
能
循环
LOOP
CX<--(CX)-1
若(CX)<>0,则循环
LOOPZ
LOOPE
CX<--(CX)-1
若(CX)<>0且ZF=1,则循环
LOOPNZ
LOOPNE
CX<--(CX)-1
当CX不为零且
若(CX)<>0且ZF=0,则循环 不相等时循环
26
当CX不为零且
相等时循环
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
循环指令示例1
求长度为10的字节数组ARRAY之和,并将和存入
TOTAL中
LEA SI, ARRAY
MOV CX, 10
MOV AX, 0
AGAIN: ADD AL, [SI]
ADC AH, 0
INC SI
LOOP AGAIN
MOV TOTAL, AX
;数组首地址-->SI
;数组长度-->CX
;求数组和
;修改指针
;存和
其中 语句 LOOP AGAIN 相当于:
DEC CX
JNZ AGAIN
27
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
循环指令示例2
在某一字节串中寻找第一个非0字节
设串首地址在DI中,串末地址在BX中
SUB BX, DI
;串长度在BX中
INC BX
MOV CX, BX
; 串字节数-->CX
DEC DI
AGAIN: INC DI
;修改指针
CMP BYTE PTR [DI], 0 ;串元素=0?
LOOPZ AGAIN
;循环查找
JNZ FOUND
;找到非0字节跳转
……
FOUND:
28
http://www.njyangqs.com/
3.6.2 串操作指令
现代微机原理与接口技术(第3版)
串——存储器中一序列字或字节单元,单元中的内
容是字符或数据
串操作——对序列字或字节单元中的内容进行某种
操作
串操作指令有7条:
1、MOVS——串传送指令
2、CMPS——串比较指令
3、SCAS——串扫描指令
4、LODS——装入串指令
5、STOS——存储串指令
6、INS——串输入
7、OUTS——串输出
29
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
说明:
每条指令有三种形式,分别对应于字节操作、
字操作和双字操作
如
MOVSB 字节操作
MOVSW 字操作
MOVSD 双字操作
与此配合使用的指令前缀有:
REP
重复
REPE/REPZ
相等/为零则重复
REPNE/REPNZ 不相等/不为零则重复
30
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
例:将字节串从源区传送到目的区
源区首偏址-->SI
目的区首偏址-->DI,串长-->CX
Y
CX=0
N
按SI所指取一字节
结束
按DI所指存此字节
(SI)+1-->SI
(DI)+1-->DI
31
(CX)-1-->CX
用一般传送指令实现
的流程图
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
源区首偏址-->SI
目的区首偏址-->DI
串长-->CX,0-->DF
CX=0
Y
N
串传送指令
(CX)-1-->CX
用串传送指令实现
的流程图
32
结束
源区首偏址-->SI
目的区首偏址-->DI
串长-->CX,0-->DF
带前缀REP的
串传送指令
用带前缀的串传送
指令实现的流程图
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
使用串操作指令时微处理器设计有若干约定:
1、源串地址由DS:SI指定
目的串地址在ES:DI中
2、串长送CX寄存器
3、设置方向标志位DF(在EFLAG寄存器中)
当DF=0(指令CLD)时地址为增量修改
(+1 或 +2 或 +4)
当DF=1(指令STD)时地址为减量修改
(-1 或 –2 或 -4)
33
http://www.njyangqs.com/
方向标志对应的指针移动示意
低地址方向
1
‘A’
...
‘J’
n
...
源串
现代微机原理与接口技术(第3版)
n
1
‘A’
…
‘J’
源串
…
目的串
目的串
高地址方向
正向传送
DF=0
34
反向传送
DF=1
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
符号
功能
MOVS 串传送
35
CMPS
串比较
SCAS
串扫描
LODS
装入串
STOS
存入串
操作
相关前缀
ES:DI<--(DS:SI)
REP
SI<--(SI)(+/-)1
DI<--(DI)(+/-)1
(DS:SI)-(ES:DI) REPZ/REPNZ
SI<--(SI)(+/-)1
DI<--(DI)(+/-)1
(ES:DI)-(AL)
REPZ/REPNZ
DI<--(DI)(+/-)1
AL<--(DS:SI)
一般不联用
SI<--(SI)(+/-)1
(ES:DI)<--(AL)
REP
DI<--(DI)(+/-)1
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
符号
INS
功能
串输入
OUTS 串输出
操作
ES:DI((DX))
DI(DI)(+/-)1
((DX))(DS:SI)
SI(SI)(+/-)1
相关前缀
REP
REP
其中DX寄存器中存放的是接口电路的端口号
36
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
重复前缀
终止条件
否则
REP
CX=0
SI,DI指向下一元素
REPZ
REPE
CX=0 或 ZF=0
CX<--(CX)-1,继续
SI,DI指向下一元素 串未结束且串相等时继续
REPNZ
REPNE
CX=0 或 ZF=1
SI,DI指向下一元素
37
CX<--(CX)-1,继续
CX<--(CX)-1,继续
串未结束且串不相等
时继续
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
例:REP MOVSB 传送过程如下:
(1)(CX)=0? 若等于0,中止传送,
否则执行下一步
(2)CX(CX)-1
(3)串传送
(4)修改指针
(5)转到(1)
38
http://www.njyangqs.com/
MOVS指令示例
MOV SI, 0050H
MOV DI, 0100H
MOV CX, 5
CLD
REP MOVSB
‘A’
‘B’
‘C’
‘D’
‘E’
‘F’
执行前
20050
00 30100
1
00
1
2
00
2
3
00
3
4
00
4
5
00
5
源区
SI=0050
39
目的区
DI=0100
现代微机原理与接口技术(第3版)
; (DS)=2000H
; (ES)=3000H
; 地址递增方式
‘A’
‘B’
‘C’
‘D’
‘E’
‘F’
执行后
‘A’
20050
‘B’
1
‘C’
2
3
‘D’
4
‘E’
5
源区
SI=0055
30100
1
2
3
4
5
目的区
DI=0105
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
CMPS指令示例
串String1和String2分别定义在数据段和附加段
中。 比较两串,如相等则转移到标号NEXT处。
String1 DB ‘HELP’
String2 DB ‘HEPP’
;定义String1
;定义String2
……
CLD
LEA SI, String1
LEA DI, String2
MOV CX, 4
REPZ CMPSB
JZ NEXT
....
NEXT:
40
;DF=0
;源串地址-->SI
;目的串地址-->DI
;重复次数-->CX
;重复比较
;串相等转移
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
SCAS指令示例
在串“That is CAI”中查找字符‘a’,找到,
则转到标号FOUND处
String DB ‘That is CAI’
;定义串
……
CLD
;DF=0
LEA DI, String
;串地址-->DI
MOV AL, ‘a’
;查找字符-->AL
MOV CX, 11
;重复次数-->CX
REPNZ SCASB
;重复扫描
JZ FOUND
;找到目的串元素转移
……
FOUND:
41
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
LODS指令示例
比较SOURCE和DESTIN (串长度为100个字节),
并将串中的第一个不匹配元素装入AL寄存器中。
……
LEA SI, SOURCE
LEA DI, DESTIN
CLD
MOV CX,100
REPZ CMPSB
JCXZ MATCH
DEC SI
LODSB
...
MATCH:
42
;源串偏移量-->SI
;目的串偏移量-->DI
;DF=0
;重复比较次数-->CX
;重复串比较
;没有不匹配元素跳转
;指向不匹配元素
;装入不匹配元素到AL
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
STOS指令示例
给首地址为BUF,长度为1000个字节的存储器区
域清零。
BUFF DB 1000 DUP(?)
;定义缓冲区
……
CLD
;DF=0
LEA DI, BUFF
;缓冲区首地址-->DI
MOV CX, 1000
;重复次数
MOV AL, 0
;0-->AL
REP STOSB
;重复存储串
43
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
综合应用例1
将存储区A到A+i中的数据传送到存储区B到B+i
中,要求存放的顺序与原先的顺序相反。
A
+1
+2
A+i
44
‘a’
‘b’
‘c’
B
+1
+2
‘b’
B+i ‘a’
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
LEA SI, A
LEA DI, B
ADD DI, I
MOV CX, I+1
LP: CLD
LODSB
STD
STOSB
DEC CX
JNZ LP
45
;DI指向存储区B的末尾
;串的长度
;DF=0
;从源区取一数据
;DF=1,改变方向
;存入目的区
http://www.njyangqs.com/
3.6.3 循环结构程序设计
现代微机原理与接口技术(第3版)
循环程序的组成:
1、初始化部分
设置初始值
2、循环工作部分 具体的操作和运算
3、循环修改部分 为执行下一循环而修改某些参数
4、循环控制部分 判断循环继续还是结束
循环控制方法有:
(1)计数控制法
增数法
减数法
(2)条件控制法
46
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
单重循环程序设计
将以s1为起始地址的26个字母依次传送到以s2为起
始地址的连续单元中。
数据定义如下:
.DATA
S1 DB ‘ABCD……XYZ’
.DATA ESTRA
S2 DB 26 DUP(?)
47
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
方法1 采用寄存器间接寻址方式
MOV AX, SEG S1 ;初始化部分
MOV DS, AX
MOV AX, SEG S2
MOV ES, AX
MOV SI, OFFSET S1
MOV DI, OFFSET S2
MOV CX, 26
LOP1: MOV AL, [SI]
;工作部分
MOV ES:[DI], AL
INC SI
;修改部分
INC DI
LOOP LOP1
;控制部分
48
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
方法2 采用串处理指令
MOV AX, SEG S1 ;初始化部分
MOV DS, AX
MOV AX, SEG S2
MOV ES, AX
LEA SI, S1
LEA DI, S2
MOV CX, 26
CLD
REP MOVSB ;工作、修改、控制合为一条指令
49
http://www.njyangqs.com/
计数控制法
现代微机原理与接口技术(第3版)
计数控制法适用于循环次数已知的场合
1、增数法
初始化时循环计数器置0,每执行一次循环体后计
数器加1,并与已知的循环次数比较,如相等则退出循
环。
增数法一般用比较指令和条件转移指令实现循环
转移。
2、减数法
初始化时循环计数器置为循环次数,每执行一
次循环体后计数器减1,并测试循环计数器是否为0,
如为0则终止循环。
减数法一般用循环指令形成循环回路。
50
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
增数法
计算S=1+2+3+···+50, 结果存入AX中
NUM DW 1 ;
......
MOV CX,0
;初始化
MOV AX,0
ROTATE:
ADD AX, NUM ;累加
INC WORD PTR[NUM]
INC CX
;计数器加1
CMP CX,50
;与已知的循环次数比较
JNZ ROTATE
MOV S, AX
......
51
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
减数法
将内存中6个十进制数的ASCII码转换为非压缩BCD码
,并存放在后继相应单元中,如错,存放0FFH。
ASCBUF DB 35H, 38H, 30H, 4DH, 39H, 32H
DB 6 DUP(?)
......
MOV DI OFFSET ASCBUF
MOV CX, 6
LAB_1:MOV BL, 0FFH
OK: MOV AL, BL
; 设置错误标志
MOV [DI+06H], AL
MOV AL, [DI]
INC DI
CMP AL, 3AH
LOOP LAB1
JNB OK ;大于等于3A则错
......
SUB AL, 30H
JC
OK ; 小于30H也错
MOV BL, AL
52
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
条件控制法
在许多情况下,事先无法确定循环次数,这时可选
用“条件”来控制循环。在问题的求解过程中,找
出一个终止循环的条件。
每循环一次,对条件进行一次检测,如满足终止循
环的条件,便退出循环,否则继续循环。
利用条件转移指令控制循环是否结束。
有些情况下为防止死循环,可以附加一个合适的循
环次数。
53
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
条件控制法
求字符串长度。从STRN地址开始有一个字符串,以
‘$’作为结束标志,长度不超过100个字节,要求统计
该字符串长度并存于LENG单元。
分析:1)设DX存放统计的串长度,为防止程序死循环
,可根据串长不超过100作为循环结束的附加条件。
2)如果程序运行过程中找到‘$’则正常退出循环,如
找不到‘$’,由于CX的初值为100,故不会使程序死循
环。
定义数据段如下:
.DATA
STRN
DB ‘XCVFATTDEQJHI…’,’$’
LENG
DB 0
54
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
LP:
DONE:
55
……
MOV AX, 0
MOV DX, AX ; DX清零
LEA DI, STRN ; 串指针赋初值
MOV CX, 100 ; 初始值为100
MOV AL, ‘$’
CMP AL, [DI]
JE
DONE
; 条件控制
INC DX
; 串长+1
INC DI
; 串指针后移一个字节
LOOP LP
; 附加条件
MOV LENG, DL; 存字符串长度
……
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
多重循环程序设计
多重循环就其本质而言,就是循环层1包含循环层2,
循环层2可能又包含循环层3…,循环层1为最外层,内
层循环是外层循环的循环体的一部分。
56
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
如果多重循环都使用
LOOP语句,则要保
护好外层循环的计数
器CX,通常采用压
栈或退栈的方法或者
转存的方法。
多重循环程序设计
57
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
有一个首地址为A的N字数组,使该数组中的数从大
到小排序 MOV CX, N
DEC CX
LOOP1: MOV DI, CX ; 暂存外循环计数值
MOV BX, 0
LOOP2: MOV AX, A[BX]
CMP AX, A[BX+2]
;比较a(i)与a(i+1)
JGE COTINUE
XCHG AX, A[BX+2]
;交换
MOV A[BX], AX
COTINUE: ADD BX, 2
LOOP LOOP2
MOV CX, DI ;恢复外循环计数值
LOOP LOOP1
58
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
3.7 子程序设计







59
子程序调用(返回)指令
过程定义伪指令
子程序的调用和返回
主程序与子程序的连接
子程序调用中的数据保护与恢复
主程序与子程序之间的参数传递
子程序嵌套与递归
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
3.7.1 子程序调用(返回)指令
1)CALL 子程序调用指令
格式1: CALL 子程序名
操作1: SP<--(SP)-2
((SP)+1,(SP))<--(IP)
IP<--(IP)+disp16
;段内直接调用
格式2:CALL reg/mem
;段内间接调用
操作2:SP<--(SP)-2
((SP)+1,(SP))<--(IP)
IP<--(reg) 或 IP<--(mem)
60
说明:1)类似于段内无条件转移指令,不同的是
需要将返回地址IP入栈
2)也可以在子程序名前使用near ptr 前缀
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
格式3:CALL FAR PTR 子程序名 ;段间直接调用
操作3:SP<--(SP)-2
((SP)+1,(SP))<--(CS)
SP<--(SP)-2
((SP)+1,(SP))<--(IP)
IP<--子程序名对应的偏移量
CS<--子程序所在的段地址
61
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
格式4:CALL DWORD PTR mem ;段间间接调用
操作4: SP<--(SP)-2
((SP)+1,(SP))<--(CS)
IP<--(SP)-2
((SP)+1,(SP))<--(IP)
IP<--(EA)
CS<--(EA+2)
说明:段间调用须保存返回地址IP和CS
386及其后继机型,用EIP代替IP
62
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
2) RET 子程序返回指令
格式
功能
RET
段内返回
IP<--((SP)+1,(SP))
SP<--(SP)+2
RET
段间返回
IP<--((SP)+1,(SP))
SP<--(SP)+2
CS<--((SP)+1,(SP))
SP<--(SP)+2
RET EXP 带立即数返回
63
操作
在上述操作之后再做
SP<--(SP)+EXP
http://www.njyangqs.com/
3.5.2 过程定义伪指令
现代微机原理与接口技术(第3版)
格式:过程名 PROC 属性
...; 过程体
RET
...; 过程体
过程名 ENDP
说明:
1、过程名是该子程序名,也是指令CALL的目标操
作数
2、过程的属性有两种:NEAR和FAR,分别表示段
内调用和段间调用。若省略,则默认为NEAR
3、至少有一条RET指令从过程中返回,可在过程中
的任何位置
64
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
3.5.3 子程序的调用和返回
主程序
子程序
.
.
.
CALL SUB
(断点)
.
.
65
SUB PROC
.
.
.
.
.
.
.
RET
http://www.njyangqs.com/
3.5.4 主程序与子程序的连接
现代微机原理与接口技术(第3版)
(1)主程序和子程序在同一代码段内
.CODE C_SEG
MAIN PROC FAR
;主程序
...
CALL SUB_A
...
MAIN ENDP
SUB_A PROC NEAR
;子程序
...
RET
SUB_A ENDP
END MAIN
66
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
(2)调用程序与子程序不在同一代码段内
;模块1
.CODE C_SEG1
……
MAIN PROC FAR
……
CALL FAR PTR SUB_1
……
RET
MAIN END
END MAIN
67
;模块2
.CODE C_SEG2
……
SUB_1 PROC FAR
……
RET
……
SUB_1 ENDP
END SUB_1
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
示例
C1段 MAIN
……
CALL FAR PTR PRO_A
0500:1000
……
C2段
PRO_A
……
CALL NEAR PTR PRO_B
2000:2500
……
CALL NEAR PTR PRO_C
2000:3700
…...
RET
68
PRO_B
……
CALL NEAR PTR PRO_C
2000:4000
……
RET
PRO_C
……
RET
转1
转2
转3
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
(1) MAIN调用PRO_A之前
SP
0100
(3) PRO_A调用PRO_B之后
00FA
2500
1000
0500
(2) MAIN调用PRO_A之后
SP
00FC
1000
0500
69
(4) PRO_B调用PRO_C之后
00F8
4000
2500
1000
0500
转
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
(5) PRO_C返回PRO_B之后
SP
00FA
4000
2500
1000
0500
(6) PRO_B返回PRO_A之后
SP
00FC
4000
2500
1000
0500
70
(7) PRO_A调用PRO_C之后
SP
00FA
4000
3700
1000
0500
转
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
(8) PRO_C返回PRO_A之后
SP
00FC
4000
3700
1000
0500
(9) PRO_A返回MAIN之后
SP
0100
4000
3700
1000
0500
转
71
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
利用程序段前缀退出程序的方法



使用DOS功能调用的4CH功能:
MOV AH, 4CH
INT 21H
使用INT 20H指令
利用程序段前缀法

72
将主程序设计成一个属性为FAR的过程,由DOS
调用该过程执行,由RET指令返回DOS(利用
程序段前缀的结构)
72 http://www.njyangqs.com/
使用程序段前缀
退出程序:
PUSH DS
MOV AX,0
PUSH AX
现代微机原理与接口技术(第3版)
操作系统加载
EXE程序时自动
在程序前加上256
字节的程序段前
缀,DS指向它
把程序段前缀区第一个字节单元的地
址和偏移量压栈保存,这个单元是指
令INT 20H,这几句一定要放在主程
序开始的位置
RET 指令
把程序段前缀区第一个字节单元的地
址和偏移量弹出分别送IP和CS,转去
执行INT 20H,从而实现返回DOS
73
INT 20H
DS
程序段前缀区
程序区
程序加载结构
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
存储单元NUM中为一个16位的二进数,统计其中值为1 的位
的个数存入RESULT
.CODE
...…
MAIN PROC FAR
JZ DONE
PUSH DS
SAL AX, 1
MOV AX,0
JNC NEXT
PUSH AX
INC CL
MOV AX, @D_SEG
NEXT: JMP LOOP1
MOV DS, AX
DONE: MOV RESULT, CL
MOV CX,0
RET
MOV AX, NUM
MAIN ENDP
LOOP1: AND AX, AX
END MAIN
本程序采用的是用RET返回DOS的方法
循环结束条件是什么?采用这样的条件有什么好处?
74
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
3.5.5 子程序调用中的数据保护与恢复
为避免在主程序和子程序中使用相同的寄存器而引起的冲
突,需要在子程序中对这些寄存器进行保护。在子程序返
回前,恢复这些寄存器原来的值。
保护和恢复现场最佳的办法就是利用堆栈。
以下就是一个保护和恢复现场的例子:
SUBT PROC NEAR
PUSH AX ;保护现场
PUSH BX
PUSH CX
……
POP CX
;恢复现场
POP BX
POP AX
; 注意弹出的顺序与压栈顺序相反
RET
SUBT ENDP
75
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
定义一个过程,它的功能是将AL中的组合BCD码转为
ASCII码,再存入BX寻址的连续的两个内存单元中。
TRAN PROC FAR
PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV DL, AL
MOV CL, 4
SHR AL, CL
OR
AL, 30H
MOV [BX], AL
INC BX
76
MOV AL, DL
AND AL, 0FH
OR AL, 30H
MOV [BX], AL
POP DX
POP CX
POP BX
POP AX
RET
TRAN ENDP
教材上的例子请看P103的例3.21
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
3.5.6 主程序与子程序之间的参数传递
参数传递的方法一般有三种:
(1) 寄存器传送
将入口参数和出口参数放在约定的寄存器中
适用于参数个数较少的情况
(2) 存储单元传递
有直接存储单元传递和地址表传递两种方法
(3) 利用堆栈传递参数
应注意避免破坏断点
77
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
寄存器传递参数示例1
十进制到十六进制数转换。从键盘取得一个十进制数
,将其以十六进数形式显示出来。
调用DECIBIN
从键盘取得十进制
数(小于65536),保
存在BX
调用CRLF
调用BINIHEX
调用CRLF
78
显示回车
和换行
用十六进制形式
显示BX中的数
http://www.njyangqs.com/
主程序:
现代微机原理与接口技术(第3版)
MAIN
PROC FAR
REPEAT: CALL DECIBIN
CALL CRLF
CALL BINIHEX
CALL CRLF
JMP REPEAT
MAIN
ENDP
79
http://www.njyangqs.com/
PROC NEAR ;出口参数BX
现代微机原理与接口技术(第3版)
PUSH AX
;保护现场
功能:从键盘取得十
PUSH CX
进制数,保存在BX
MOV BX, 0
NEWCHAR: MOV AH, 1
INT 21H
;读键盘,输入的ASCII在AL中
SUB AL, 30H
JL
EXIT
;小于0转
CMP AL, 9
JG
EXIT
;大于9转
CBW
; 字节转成字
XCHG AX, BX
MOV CX, 10
MUL CX
; 将以前的值乘以10
XCHG AX, BX
ADD BX, AX
; 加这一次读的值
JMP NEWCHAR
EXIT:
POP CX
;恢复现场
POP AX
RET
80DECIBIN
http://www.njyangqs.com/
ENDP
DECIBIN
BINIHEX PROC NEAR
……
MOV CH, 4
ROTATE: MOV CL, 4
ROL BX, CL
MOV AL, BL
AND AL, 0FH
ADD AL, 30H
CMP AL, 3AH
JL
PRINTIT
ADD AL, 7
PRINTIT: MOV DL, AL
MOV AH, 2
INT 21H
DEC CH
JNZ ROTATE
……
RET
81 BINIHEX ENDP
现代微机原理与接口技术(第3版)
;入口参数BX
;循环4次(BX中有4位16进制数)
; 循环左移四位,从最高位输出
;是0--9
;是A--F
;显示(输出)DL中的一个字符
功能:用十六进制形
式显示BX中的数
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
CRLF
CRLF
82
PROC NEAR
PUSH AX
PUSH DX
MOV DL, 0DH
MOV AH, 2
INT
21H
MOV DL, 0AH
MOV AH, 2
INT
21H
POP DX
POP AX
RET
ENDP
功能:显示回车和换行
;回车
; 输出DL中的字符
; 换行
; 输出DL中的字符
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
寄存器传递参数示例2 求数组元素之和。
.DATA
ARRAY DB 10,20,30,5,60
COUNT EQU $-ARRAY ;数组元素个数
.STACK 100H
.CODE
START: ...
LEA SI, ARRAY
;参数准备
MOV CX, COUNT
CALL SUM1
;求和
……
83
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
;子程序:SUM1
;入口参数:SI=数组首址,CX=数组长度
;出口参数:AX=数组和
;使用寄存器:AX, CX, SI
SUM1 PROC NEAR
……
CMP CX,0
JZ EXIT
XOR AX, AX
AGAIN: ADD AL, [SI]
ADC AH,0
INC SI
LOOP AGAIN
EXIT:
……
RET
SUM1 ENDP
84
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
直接存储单元传送示例
求数组元素之和,结果送SUM单元
.DATA
ARRAY DW 100 DUP(?)
COUNT DW 100
SUM DW ?
.CODE
......
CALL PROADD
;主程序
......
85
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
PROADD PROC
PUSH AX
;保存现场
PUSH CX
PUSH SI
XOR AX, AX
LEA SI, ARRAY
;直接使用存储单元中数据
MOV CX, COUNT
NEXT: ADD AX, [SI]
ADD SI, 2
LOOP NEXT
MOV SUM, AX
;结果直接送SUM
POP SI
;恢复现场
POP CX
POP AX
RET
PROADD ENDP
86
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
地址表传递示例
调用子程序前,把所有参数的地址送入地址表,然后把地址表
的偏移量通过寄存器带进子程序,子程序从地址表中取得参数
地址。
求数组之和
.DATA
ARRAY DW 50 DUP(?)
COUNT DW 50
SUM DW ?
TABLE DW 3 DUP(?)
......
MOV TABLE, OFFSET ARRAY
MOV TABLE+2, OFFSET COUNT
MOV TABLE+4, OFFSET SUM
TABLE ARRAY首址
LEA BX, TABLE
+2 COUNT地址
CALL PROADD
+4 SUM地址
......
87
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
PROADD PROC
;入口参数 BX为地址表首地址
PUSHA
;保护现场
MOV SI, [BX]
;数组首地址送SI
MOV DI, [BX+2]
;数组长度单元地址送DI
MOV CX, [DI]
;数组长度送CX
MOV DI, [BX+4]
;存储和的单元地址送DI
MOV AX, 0
ADDT: ADD AX, [SI]
ADD SI, 2
LOOP ADDT
MOV [DI], AX
POPA
;恢复现场
RET
PROADD ENDP
88
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
利用堆栈传递参数示例——求数组之和
主程序中:
LEA BX, ARRAY
;参数进栈
PUSH BX
注意,一
LEA BX, COUNT
共3个参数
PUSH BX
进栈,每
LEA BX, SUM
个占2字节
PUSH BX
CALL FAR PTR PROADD
......
PROADD PROC FAR
PUSH BP
;保护现场
MOV BP, SP
PUSH AX
PUSH CX
新BP
PUSH SI
高地址
PUSH DI
89
(DI)
(SI)
(CX)
(AX)
原始(BP)
(IP)
(CS)
SUM地址
COUNT地址
ARRAY地址
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
MOV SI, [BP+10] ;取得参数地址
MOV DI, [BP+8]
SP
MOV CX, [DI]
MOV DI, [BP+6]
MOV AX, 0
ADDT: ADD AX, [SI]
ADD SI,2
BP
LOOP ADDT
BP+2
MOV [DI],AX ;保存结果
POP DI
;恢复现场
BP+4
POP SI
BP+6
POP CX
POP AX
BP+8
POP BP
BP+10
RET 6; 弹出压栈的6字节参数
高地址
PROADD ENDP
90
(DI)
(SI)
(CX)
(AX)
原始(BP)
(IP)
(CS)
SUM地址
COUNT地址
ARRAY地址
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
子程序嵌套
程序设计中,子程序A调用子程序B,子程序B
调用子程序C......这一过程称为子程序嵌套。
CALL
CALL
CALL
主程序
RET
子程序1
RET
子程序2
RET
子程序N
注意:
1、每一层调用都要注意寄存器的保存和恢复
2、PUSH ,POP 的使用要严格平衡,确保自内向外顺序退出
91
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
递归子程序
当一个程序直接或间接调用其自身时,称为递归调用.
递归子程序示例——阶乘函数的计算
......
Y
N
n=0
N
DB 4
1-->F
RESULT DW ?
n进栈
主程序:
n-1-->n
求出基数返回
MOV AL, N
CALL FACT
递归调用
ADD1:
MOV RESULT, DX
弹出n
n*F-->F
92
递归返回
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
FACT PROC
;入口参数AL(N的值)
,出口参数N!=DX
CMP AL, 0
;N=0?
JNZ F1
;N<>0跳转
MOV DX, 1
;(DX)<--1
RET
F1:
PUSH AX
;N进栈
DEC AL
;(AL)<--N-1
CALL FACT
;递归
ADD2: POP CX
;(CX)<--N
CALL MULT
;(DX)<--N*FACT(N-1)
RET
FACT ENDP
MULT PROC ; 入口CL中是N,DX中是FACT(N-1)
MOV AL, CL ; 出口参数DX中是N*FACT(N-1)
MUL DL
MOV DX, AX
RET
93 MULT ENDP
http://www.njyangqs.com/
现代微机原理与接口技术(第3版)
94
http://www.njyangqs.com/