1
? 循环程序设计
? 分支程序设计
? 子程序结构设计
? 宏汇编程序设计
? 中断程序设计( 第 4章 )
3.3 微处理器编程
2
分支结构 子程序结构
一、基本程序结构
复合结构:多种程序结构的组合

顺序结构 循环结构
3
编制汇编语言程序的步骤,
(1) 分析题意,确定算法
(2) 根据算法画出程序框图
(3) 根据框图编写程序
(4) 上机调试程序
4
1,循环程序设计
DO-WHILE 结构 DO-UNTIL 结构
控制条件
初始化
循环体
Y
N
控制条件
初始化
循环体
Y
N
5
初始化, 设置循环的初始状态
循环体, 循环的工作部分及修改部分
控制条件, 计数控制
特征值控制
地址边界控制
6
BX
1
2
3
4
例 1:把 BX 中的二进制数以十六进制的形式显示在屏幕上
7
……
mov ch,4
rotate,mov cl,4
rol bx,cl
mov al,bl
and al,0fh
add al,30h ; ’0’~’9’ ASCII 30H~39H
cmp al,3ah
jl printit
add al,7h ; ’A’~’F’ ASCII 41H~46H
printit,mov dl,al
mov ah,2
int 21h
dec ch
jnz rotate
……
8
……
mov bx,0
newchar,mov ah,1 ;键盘输入
int 21h
sub al,30h
jl exit ; <0退出
cmp al,9
jg exit ; >9退出
cbw
xchg ax,bx
mov cx,10
mul cx
xchg ax,bx
add bx,ax
jmp newchar
exit,……
例 2:从键盘接收十进制数并存入
BX
( ( 0× 10)+1 )× 10+2 )× 10+5
1 2 5
31 32 35
9
……
mov bx,0
newchar,mov ah,1 ;键盘输入
int 21h
sub al,30h
jl exit ; <0退出
cmp al,10
jl add_to
sub al,27h ; ‘a’~‘f’
cmp al,0ah
jl exit ; <‘a’退出
cmp al,10h
jge exit ; >’f’退出
add_to,mov cl,4
shl bx,cl
mov ah,0
add bx,ax
jmp newchar
exit,……
例 3:从键盘接收十六进制数并存入 BX 1 a f
31 61 66
((0× 16)+1) × 16+0a) × 16+0f
10
例 4,在字数组的第 4和第 5个元素之间插入 5个 0
array dw 64 dup (?)
buffer dw 5 dup (?);
start,mov ax,@data
mov ds,ax
mov es,ax;
mov si,offset buffer-2
mov di,offset buffer+8
mov cx,60
std
rep movsw;
mov ax,0
mov cx,5
rep stosw
… …
array+0
buffer
a
b c
d e
+2
60
0
0
0
0
0
+8
- -
- -
-
#
11
例 5,将正数 n 插入一个已整序的正数字数组
(1) 算法,
n< Ki,则 Ki下移一个单元
n≥Ki,则插入 Ki的下一单元,程序结束
(2) 边界情况,
n≥Kn,则插入最后一个单元
n< K1,则 K1~ Kn后移,n插入第一单元
(3) 循环控制,
● 计数控制:元素个数=(末址-首址) /2+ 1
● 地址边界控制:结束地址为 array_head
● 特征值控制:具有区别特征的值,如- 1(- 1< n< K1)
12
x dw?
array_head dw 3,5,15,23,37,49,52,65,78,99
array_end dw 105
n dw 32
例 5,将正数 n 插入一个已整序的正数字数组
……
mov ax,n
mov array_head-2,0ffffh
mov si,0
compare,
cmp ax,array_end [si]
jge insert
mov bx,array_end [si]
mov array_end [si+2],bx
sub si,2
jmp short compare
Insert,
mov array_end [si+2],ax
……
3
5
15
23
37
49
52
65
78
99
105
32
-1
array_head?
array_end?
n ?
x ?
13
例 6, 将首地址为 A的字数组从小到大排序
( 气泡算法, 多重循环 ) 32,85,16,15,8
序号 地址 数
比 较 遍 数
1 2 3 4
1 A 32
2 A+2 85
3 A+4 16
4 A+6 15
5 A+8 8
32
16
15
8
85
16
15
8
32
85
15
8
16
32
85
8
15
16
32
85
14
mov cx,5 ;元素个数
dec cx ;比较遍数
loop1,mov di,cx ;比较次数
mov bx,0
loop2,
mov ax,A[bx] ;相邻两数
cmp ax,A[bx+2] ; 比较
jle continue
xchg ax,A[bx+2] ;交换位置
mov A[bx],ax
continue,
add bx,2
loop loop2
mov cx,di
loop loop1
15
2,分支程序设计

case 1 case 2 case n
case 1 case 2 case n
CASE 结构 IF-THEN-ELSE 结构
(1) 逻辑尺控制
(2) 条件控制
(3) 地址跳跃表 (值与地址有对应关系的表)
16
例 1:有数组 x(x1,x2,……,x10) 和 y(y1,y2,……,y10)
编程计算 z(z1,z2,……,z10)
z1 = x1 + y1
z2 = x2 + y2
z3 = x3 - y3
z4 = x4 - y4
z5 = x5 - y5
z6 = x6 + y6
z7 = x7 - y7
z8 = x8 - y8
z9 = x9 + y9
z10= x10 + y10
逻辑尺,0 0 1 1 0 1 1 1 0 0
1 减法
0 加法
17
x dw x1,x2,x3,x4,x5,x6,x7,x8,x9,x10
y dw y1,y2,y3,y4,y5,y6,y7,y8,y9,y10
z dw z1,z2,z3,z4,z5,z6,z7,z8,z9,z10
logic_rule dw 00dch ;0000,0000,1101,1100
……
mov bx,0
mov cx,10
mov dx,logic_rule
next,mov ax,x[bx]
shr dx,1
jc subtract
add ax,y[bx]
jmp short result ; 向前引用
subtract,
sub ax,y[bx]
result,mov z[bx],ax
add bx,2
loop next
……
18
data segment
array dw 12,11,22,33,44,55,66,
DW 77,88,99,111,222,333
number dw 55
low_idx dw?
high_idx dw?
data ends
例 2:折半查找算法
19
12
11
22
33
44
55
66
77
88
99
111
222
333
0
1
2
3
4
5
6
7
8
9
10
11
12
(ax)=55
low_idx
1
1
4
5
high_idx
12
5
5
5
(si)=0ah
Cf=0
(ax)=90
low_idx
1
7
7
8
9
high_idx
12
12
8
8
8
(si)=10h
Cf=1
?
?
?
?
折半算法
?
?
?
20
……
lea di,array
mov ax,number ;要查找数
cmp ax,[di+2] ; (ax)与第一个元素比较
ja chk_last
lea si,[di+2]
je exit ; (ax)=第一个元素,找到退出
stc
jmp exit ; (ax)<第一个元素,未找到 退出
chk_last,
mov si,[di] ;元素个数
shl si,1 ; 计算 最后一个元素
add si,di ; 的地址
cmp ax,[si] ; (ax)与最后一个元素比较
jb search
je exit ; (ax)=最后一个元素,找到退出
stc
jmp exit ; (ax)>最后一个元素,未找到 退出
21
compare,
cmp ax,[bx+si]
je exit
ja higher
dec cx
mov high_idx,cx
jmp mid
higher,
inc cx
mov low_idx,cx
jmp mid
no_match,
stc
exit,
……
search,
mov low_idx,1
mov bx,[di] ;个数
mov high_idx,bx
mov bx,di
mid,
mov cx,low_idx
mov dx,high_idx
cmp cx,dx
ja no_match
add cx,dx
shr cx,1
mov si,cx
shl si,1
22
例 3,根据 AL 寄存器中哪一位为 1( 从低位到高位 ),
把程序转移到 8 个不同的程序分支
branch_table dw routine1
dw routine2
dw routine3
dw routine4
dw routine5
dw routine6
dw routine7
dw routine8
23
……
cmp al,0 ;AL为逻辑尺
je continue
lea bx,branch_table
L,shr al,1 ;逻辑右移
jnc add1
jmp word ptr[bx] ;段内间接转移
add1,add bx,type branch_table ; add bx,2
jmp L
continue,
……
routine1,
……
routine2,
……
( 寄存器间接寻址 )
24
( 寄存器相对寻址 ) ……
cmp al,0
je continue
mov si,0
L,shr al,1 ;逻辑右移
jnc add1
jmp branch_table[si] ;段内间接转移
add1,
add si,type branch_table
jmp L
continue,
……
routine1,
……
routine2,
……
25
( 基址变址寻址 ) ……
cmp al,0
je continue
lea bx,branch_table
mov si,7 * type branch_table
mov cx,8
L,shl al,1 ;逻辑左移
jnc sub1
jmp word ptr [bx][si] ;段内间接转移
sub1,sub si,type branch_table ;(si)-2
loop L
continue,
……
routine1,
……
routine2,
……
26
3.子程序结构
? 过程定义伪操作
? 子程序的调用与返回
? 保存与恢复寄存器
? 子程序的参数传送
? 子程序的嵌套与递归
27
(1) 过程定义伪操作
过程名 PROC NEAR ( FAR )
过程名 ENDP
( 1) NEAR属性:调用程序和子程序在同一代码段中
( 段内调用 )
( 2) FAR属性:调用程序和子程序不在同一代码段中
( 段间调用 )
.,
,
28
code segment
main proc far
……
call subr1
……
ret
main endp
subr1 proc near
……
ret
subr1 endp
code ends
segx segment
subt proc far
……
ret
subt endp
……
call subt
……
segx ends
segy segment
……
call far ptr subt
……
segy ends
29
子程序调用,隐含使用堆栈保存返回地址
call near ptr subp
(1) 保存返回地址
(2) 转子程序
call far ptr subp
(1) 保存返回地址
(2) 转子程序
子程序返回,ret
(2) 子程序的调用与返回
(SP)→ (IP)
(IP)
(CS)
(SP)→
30
(3) 保存与恢复寄存器
subt proc far
push ax
push bx
push cx
push dx
……
……
pop dx
pop cx
pop bx
pop ax
ret
subt endp
31
(a) 利用寄存器传送参数
(b) 利用存储器传送参数
(c) 通过地址表传送参数地址
(d) 利用堆栈传送参数或参数地址
(4) 子程序的参数传送
32
例 1:累加数组中的元素 ( 通过地址表传送参数地址 )
data segment
ary dw 10,20,30,40,50,60,70,80,90,100
count dw 10
sum dw?
table dw 3 dup (?) ; 地址表
data ends
code segment
main proc far
assume cs:code,ds:data
push ds
sub ax,ax
push ax
mov ax,data
mov ds,ax
mov table,offset ary
mov table+2,offset count
mov table+4,offset sum
mov bx,offset table
call proadd
ret
main endp
33
proadd proc near
push ax
push cx
push si
push di
mov si,[bx]
mov di,[bx+2]
mov cx,[di]
mov di,[bx+4]
xor ax,ax
next,
add ax,[si]
add si,2
loop next
mov [di],ax
pop di
pop si
pop cx
pop ax
ret
proadd endp
code ends
end main
30d
40d
50d
60d
70d
80d
90d
100d
10d
ary?
20d
10d
count?
sum?
table?
0000
0014
0016
0018 0000
0014
0016
?(bx)
(si)
(di) 550d
34
例 2:累加数组中的元素( 通过堆栈传送参数地址 )
data segment
ary dw 10,20,30,40,50,60,70,80,90,100
count dw 10
sum dw?
data ends
stack segment
dw 100 dup (?)
tos label word
stack ends
35
code1 segment
main proc far
assume cs:code1,ds:data,ss:stack
start,
mov ax,stack
mov ss,ax
mov sp,offset tos
mov ax,data
mov ds,ax
mov bx,offset ary
push bx
mov bx,offset count
push bx
mov bx,offset sum
push bx
call far ptr proadd
mov ax,4c00h
int 21h
main endp
code1 ends
36
code2 segment
assume cs:code2
proadd proc far
push bp
mov bp,sp
push ax
push cx
push si
push di
mov si,[bp+0ah]
mov di,[bp+8]
mov cx,[di]
mov di,[bp+6]
code2 ends
end start
xor ax,ax
next,
add ax,[si]
add si,2
loop next
mov [di],ax
pop di
pop si
pop cx
pop ax
pop bp
ret 6
proadd endp
(ip)
(cs)
sum
count
array
?
(di)
(si)
(cx)
(ax)
(sp)?
(bp)? (bp)
(bp)+0ah?
(bp)+8?
(bp)+6?
tos
37
子程序的嵌套,
主程序 子程序 A 子程序 B
递归子程序,n! = n ( n - 1 ) ( n - 2 ) …1
3! = 3 × 2× 1= 6
(5) 子程序的嵌套与递归调用
……
call proc_A
……
proc_A
……
call proc_B
……
Call proc_A
ret
proc_B
……
ret
38
fact proc near
push ax
push bp
mov bp,sp
mov ax,[bp+6]
cmp ax,0
jne fact1
inc ax
jmp exit
fact1,dec ax
push ax
call fact
pop ax
mul word ptr[bp+6]
exit,mov [bp+6],ax
pop bp
pop ax
ret
fact endp
例 3,计算 n!
mov bx,n_v
push bx
call fact
pop result
主程序,
?
(BP)
(AX)
(IP)
0
(BP)
(AX)
(IP)
1
(BP)
(AX)
(IP)
2
(BP)
(AX)
(IP)
3
?
?
?
39
? 宏 汇编
? 宏汇编伪操作
? 建立宏指令库
4.宏结构程序设计
40
( 1) 宏汇编
宏, 源程序中一段有独立功能的程序代码。
宏指令, 用户自定义的指令。在编程时,将多次
使用的功能用一条宏指令来代替。
汇编语言程序
指令
伪指令 ( 伪操作 )
宏指令
41
优,模块化
省内存
缺,开销大
宏定义,
Q macro x,y

endm
主程序,

Q a,b

Q c,d

Q e,f

目标程序,






优,
参数传送
简单,执
行效率高
缺,
占用内存
空间大
主程序,

CALL ----

CALL ----

CALL ----

子程序,



RET
42
宏展开,汇编程序把 宏调用 展开
宏定义体 复制到宏指令位置,实参代虚参
LOCAL中的标号0000~ffff
宏定义,
macro_name MACRO [哑元表 ] ; 形参 /虚参
[LOCAL 标号表 ]
……
…… ; 宏定义体
ENDM
宏调用,(必须先定义后调用)
macro_name [实元表 ] ; 实参
43
例:保存寄存器
宏展开,
1 push ax
1 push bx
1 push cx
1 push dx
1 push si
1 push di
宏定义,
savereg MACRO
push ax
push bx
push cx
push dx
push si
push di
ENDM
宏调用,
savereg
44
例:两个字相乘
宏定义,
multiply MACRO opr1,opr2,result
push dx
push ax
mov ax,opr1
imul opr2
mov result,ax
pop ax
pop dx
ENDM
宏调用,
multiply cx,var,xyz[bx]
宏展开,
1 push dx
1 push ax
1 mov ax,cx
1 imul var
1 mov xyz[bx],ax
1 pop ax
1 pop dx
45
例:求绝对值
宏定义,
absol MACRO oper
LOCAL next
cmp oper,0
jge next
neg oper
next,
ENDM
宏调用,
……
absol var
……
absol bx
……
宏展开,
……
1 cmp var,0
1 jge0000
1 neg var
10000,
……
……
1 cmp bx,0
1 jge0001
1 neg bx
10001,
……
( 2) 宏汇编伪操作
局部标号伪操作 LOCAL
46
宏汇编操作符,& ;; %
符号 1 & 符号 2
宏展开时,合并前后两个符号形成一个符号 。
;; 注释
宏展开时,;;后面的注释不予展开。
% 表达式
汇编程序将 %后面的表达式转换为数字,并在
展开期间用这个数取代哑元。
47
leap macro cond,lab
j&cond lab
endm
宏定义,
宏调用,
leap z,there
……
leap nz,here
宏展开,
1 jz there
……
1 jnz here
48
宏定义,msg macro lab,num,xyz
lab&num db ‘HELLO MR.&xyz’
endm
宏调用,msg ary,1,wang ……
msg ary,2,zhang
宏展开,
1 ary1 db ‘HELLO MR.wang’
……
1 ary2 db ‘HELLO MR.zhang’
49
例:定义宏指令 STRG,实现存储字符串的功能
宏定义,STRG MACRO STRING
DB ‘&STRING&’
ENDM
宏调用, STRG 25- 1
STRG % 25 - 1
宏展开,1 DB ‘25- 1’
1 DB ‘24’
50
宏定义,msg macro count,string
msg&count db string
endm
errmsg macro text
cntr = cntr+1
msg %cntr,text
endm
宏调用,
cntr=0
……
errmsg ‘SYNTAX ERROR’
……
errmsg ‘INVALID OPERAND’
宏展开,
1 cntr = cntr+1
1 msg %cntr,‘SYNTAX ERROR’
2 msg1 db ‘SYNTAX ERROR’
……
1 cntr = cntr+1
1 msg %cntr,‘INVALID OPERAND’
2 msg2 db ‘INVALID OPERAND’
51
列表伪操作,
.LALL, 在 LST清单中列出宏展开后的全部
语句 (包括注释 )。
.SALL, 在 LST清单中不列出任何宏展开后的
语句 。
.XALL, 缺省的列表方式, 只列出宏体中产生
目标代码的语句 。
52
starter macro csname,dsname
assume cs:csname,ds:dsname,es:dsname
push ds
sub ax,ax
push ax
mov ax,dsname
mov ds,ax
mov es,ax
endm
宏调用,
,xall
starter code,data
1 push ds
1 sub ax,ax
1 push ax
1 mov ax,data
1 mov ds,ax
1 mov es,ax
53
( 3) 建立宏指令库
macro1 MACRO [哑元表 ]
……
ENDM
macro2 MACRO [哑元表 ]
……
ENDM
……
macroN MACRO [哑元表 ]
……
ENDM
>EDIT EXP.ASM include MACRO.MAC
……
macro1 [实元表 ]
……
macro2 [实元表 ]
……
macroN [实元表 ]
……
purge macroN
>EDIT MACRO, MAC
调用宏库,
54
● 键盘 I/O
● 显示器 I/O
二、使用键盘和显示器
55
子程序调用
主程序
……
CALL SUBP
……
子程序
……
……
RET
DOS/BIOS调用
源程序
……
INT n
……
DOS/BIOS
例行程序
……
……
IRET
实现机制不同
56
例,DOS调用:键盘输入,显示输出
MOV AH,01 ;DOS功能号,键盘输入
INT 21H ;DOS调用
MOV CHAR,AL ;返回参数, (AL)
MOV DL,’A’ ;调用参数, 输出字符
MOV AH,02 ; DOS功能号, 显示输

INT 21H ; DOS调用
57
BIOS和 DOS基本调用
调用方法,
1、将 调用参数 装入 指定的 寄存器中;
2,BIOS或 DOS功能号 装入 AH;
3、如需 子功能号,把它装入 AL;
4、按中断号 调用 DOS或 BIOS中断 (INT);
5、检查或取得 返回参数 。
58
1,键盘 I/O
(1) BIOS键盘中断 ( INT 16H)
AH 功能 返回参数
0 从键盘读一字符 AL=字符码,AH=扫描码
1 读键盘缓冲区的字符 如 ZF=0,AL=字符码,
AH=扫描码
如 ZF=1,缓冲区空
2 取键盘状态字节 AL=键盘状态字节
? 字符数字键 字符码为 ASCII 码
? 功能键、控制键 字符码为 0
对应一个 扫描码
59
(1) DOS键盘中断 ( INT 21H)
AH 功 能 调用参数 返回参数
1 从键盘输入一个字符并回显在屏幕上 AL=字符
6 读键盘字符, 不回显 DL= 0FFH 若有字符可取, AL=字符, ZF=0
若无字符可取, AL=0,ZF=1
7 从键盘输入一个字符, 不回显 AL=字符
8 从键盘输入一个字符, 不回显, AL=字符
检测 Ctrl-Break
A 输入字符到缓冲区 DS:DX = 缓冲区首址
B 读键盘状态 AL=0FFH有键入, AL=00无键入
C 清除键盘缓冲区, AL=键盘功能号
并调用一种键盘功能 ( 1,6,7,8或 A)
60
例, 输入字符串到缓冲区 STRING
DATA SEGMENT
MAXLEN DB 32 MAXLEN DB 32,0,32 DUP(?)
ACTLEN DB? MAXLEN DB 32,33 DUP(?)
STRING DB 32 DUP(?)
DATA ENDS
CODE SEGMENT

LEA DX,MAXLEN
MOV AH,0AH
INT 21H

CODE ENDS
END
32
5
68H
61H
70H
70H
79H
0DH
MAXLEN
ACTLEN
STRING
61
2.显示器 I/O
文本方式 ASCII字符
7 6 5 4 3 2 1 0
7 6 5 4 3 2 1 0
前景
000 = 黑
111 = 白 亮度
0 = 正常亮度
1 = 加强亮度
闪烁
0 = 正常显示
1 = 闪烁显示
背景
000 = 黑
111 = 白
单色属性
7 6 5 4 3 2 1 0
前景
闪烁
背景
BL R G B I R G B 16色属性
62
(1) BIOS显示中断 INT 10H
功能号 AH=0,1,2,3,5,6,7,8,9,0AH,0EH 13H (p.164)
例:清除屏幕
mov ah,6 ; 屏幕初始化
mov al,0 ; 全屏空白
mov bh,7 ; 卷入行属性
mov ch,0 ; 左上角行号
mov cl,0 ; 左上角列号
mov dh,24 ; 右下角行号
mov dl,79 ; 右下角列号
int 10h ; BIOS调用
定义窗口
63
例, 在品红背景下, 显示 5个浅绿色闪烁的星号 。
MOV AH,09 ; 光标位置下显示
MOV AL,’ *’ ; 显示字符
MOV BH,0 ; 显示页 0
MOV BL,0DAH ; 1 101 1010 (表 3-10)
MOV CX,05 ; 显示次数
INT 10H ; BIOS调用
64
例,在屏幕上以红底兰字显示字符串:, WORLD SCENERY”
STRING DB ‘WORLD SCENERY’ ;定义在 ES段
LEN_TR DW 13

MOV AL,3 ;80× 25,16色文 本方式
MOV AH,0
INT 10H
MOV BP,SEG STRING
MOV ES,BP ;串地址 ES:BP
MOV BP,OFFSET STRING
MOV CX,LEN_STR ;串长度
MOV DX,0 ;起始行列
MOV BX,0041H ;0100 0001( 属性 )
MOV AL,1 ;子功能
MOV AH,13H ;显示字符串
INT 10H
65
(2) DOS显示功能调用中断 INT 21H
AH 功 能 调 用 参 数
2 显示一个字符 (检验 Ctrl-Break) DL = 字符
光标跟随字符移动
6 显示一个字符 (不检验 Ctrl-Break) DL = 字符
光标跟随字符移动
9 显示字符串 DS:DX=串地址
串必须以 $结束,
光标跟随串移动
66
例:显示字符串
MESSAGE DB ‘The sort operation is finished.’,13,10,’$’
… …
MOV AH,9
MOV DX,SEG MESSAGE
MOV DS,DX
MOV DX,OFFSET MESSAGE
INT 21H