【 本章重点 】 熟练掌握汇编语言的四种程序设计方法:
顺序程序设计,分支程序设计,循环程序
设计以及子程序设计。
【 本章难点 】 确定算法,合理分配内存工作单元。
第 4章 汇编语言程序设计
§ 4.1 汇编语言程序设计概述
4.1.1 汇编语言程序设计步骤
使用汇编语言设计一个程序大致上可分为以下几个步
骤 。
(1) 分析问题, 明确要求 。 解决问题之前, 首先要明确
所要解决的问题和要达到的目的, 技术指标等 。
(2) 确定算法 。 根据实际问题的要求, 给出的条件及特
点, 找出规律性, 最后确定所采用的计算公式和计算方
法, 这就是一般所说的算法 。 算法是进行程序设计的依
据, 它决定了程序的正确性和程序的指令 。
(3) 画程序流程图,用图解来描述和说明解题步骤。
(4) 分配内存工作单元, 确定程序与数据区的存
放地址 。
(5) 编写源程序 。
(6) 程序优化 。
( 7) 程序调试, 修改和最后确定源程序 。 只有通过
上机调试并得出正确结果的程序, 才能认为是正确的
程序 。 没有调试过的程序, 很难保证程序无错误, 程
序调试是不可缺省的 。
§ 4.2顺序程序设计
对于一些简单的数据处理,只要把完成处理的各个步骤用
汇编语言描述清楚,让计算机按指令编写的次序从头到尾
一条条执行即可,这样的程序结构称为顺序结构。
【 例 4-1】 已知 X和 Y是数据段中的两个无符号字节单元,
用程序完成表达式 Z=( X2+ Y2) /2的计算。
编制程序如下:
DATA SEGMENT
X DB 15
Y DB 34
Z DW?
DATA ENDS
CODE SEGMENT
ASSUME CS,CODE,DS,DATA
START,MOV AX,DATA
MOV DS,AX ;初始化数据段
MOV AL,X ; X中的内容送 AL
MUL AL ;计算 X× X
MOV BX,AX ; X× X乘积送 BX
MOV AL,Y ; Y中的内容送 AL
MUL AL ;计算 Y× Y
ADD AX,BX ;计算 X2+ Y2
SHR AX,1 ;计算( X2+ Y2) /2
MOV Z,AX ;结果送 Z单元
MOV AH,4CH
INT 21H ;返回 DOS
CODE ENDS
END START ;汇编结束
【 例 4-2】 从键盘读入两个一位数 ( 按键时保证按下的是数
字键 ), 显示它们的积 。
先后从键盘上读取两个按键,分别减去 30H得到它们对应的
数值,然后相乘分解成十位数字与个位数字,转换成 ASCⅡ
码后依次输出即可。为了输入输出效果的直观,有必要在每
次按键后回车换行。
CODE SEGMENT
ASSUME CS,CODE
MAIN,MOV AH,1
INT 21H ;读入第 1个数字
MOV BL,AL ;保存在 BL中
MOV AH,2
MOV DL,13
INT 21H ;回车
MOV DL,10
INT 21H ;换行
MOV AH,1
INT 21H ;读入第 2个数字
SUB AL,30H ;第 2个数字转换成十进制数
SUB BL,30H ;第 1个数字转换成十进制数
MUL BL ;两个数相乘,积在 AX中
MOV BL,10 ;
DIV BL ;积除以 10取商送 AL,余数在 AH中
ADD AX,3030H ;转换成相应的 ASCⅡ 码
MOV BX,AX ;保存在 BX中
MOV AH,2
MOV DL,13
INT 21H ;回车
MOV DL,10
INT 21H ;换行
MOV DL,BL
MOV AH,2
INT 21H ;输出十位数
MOV DL,BH
INT 21H ;输出个位数
MOV AH,4CH
INT 21H ;返回 DOS
CODE ENDS
END MAIN ;程序结束
§ 4.3分支程序设计
分支程序是利用条件转移指令,使程序执行到某一
指令后,根据条件是否满足,来改变程序执行的次
序。在程序设计中经常会遇到各种判断和比较,例
如, 相等, 和, 不相等, ;, 正, 和, 负, ;, 大
于, 和, 小于, ;, 满足条件, 和, 不满足条件,
等等,这些判断和比较在程序中都可以组成各种不
同的逻辑框,并产生相应的分支程序。
分支程序段2
分支程序段3 分支程序段1
结束
条件1
条件2




【 例 4-3】 已知 AX中放有一个带符号数,编写程序
段,计算它的绝对值。
AX ← 0-AX
AL< 0?
Y
N

CMP AX,0
JGE LOOP
MOV BX,AX
MOV AX,0
SUB AX,BX
LOOP,┇

1 当 X>0
【 例 4-4】 符号函数 Y= 0 当 X=0 ( - 128≤ X≤+ 127)
- 1 当 X<0
设任意给定的 X存放在 XX单元, 计算出函数 Y值要求存放在
YY单元 。
开始
XX →AL
-1 →AL
1 →AL
AL →YY 单元
AL ≥0
AL =0
Y
N
结束
TA SEGMENT
XX DB 0F0H
YY DB?
DATA ENDS
CODE SEGMENT
ASSUME CS,CODE,DS,DATA
START PROC FAR
PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DATA
MOV DS,AX
MOV AL,XX
CMP AL,0
JGE BIGR
MOV AL,0FFH
MOV YY,AL
RET
BIGR,JE EQUL
MOV AL,1
EQUL,MOV YY,AL
RET
START ENDP
CODE ENDS
END START
§ 4.4循环程序设计
循环程序是强制 CPU重复执行某一指令系列的一种程
序结构形式, 它可以使许多重复工作的程序大为简化,
而且减少内存空间 。 被重复执行的部分称作循环体, 要
想把循环体多次执行, 就必须在循环体的前后有相应的
指令实现循环控制 。
循环程序一般由 4部分组成:
初始化、循环体、循环控制和循环结束处理
开始
初始化
循环体
循环控制
判断
结束处理
结束


开始
外循环初始化
内循环初始化
内循环体
内控制
外循环体
外控制
结束




循环程序分为单循环和多重循环,两重以上
循环称为多重循环
【 例 4-5】 现将以 AREA1为首地址的 100个字节数据搬移
到以 AREA2为首地址的内存中去 。
程序如下:
DATA SEGMENT
AREA1 DB 100DUP(?)
ATEA2 DB 100DUP( 00)
DATA ENDS
CODE SEGMENT
ASSUME CS,CODE,DS,DATA
START,MOV AX,DATA
MOV DS,AX
MOV SI,OFFSET AREA1
MOV DI,OFFSET ATEA2
MOV CX,100
AGAIN,MOV AL,[SI]
MOV [DI],AL
INC SI
INC DI
DEC CX
JNZ AGAIN
MOV AH,4CH
INT 21H
CODE ENDS
END START
【 例 4-6】 若有一串无符号数, 放在 NUM开始的单元中,
要求编制汇编语言程序, 将其中的最大值找出来, 且放到
存储单元 MAX中, 这串数的长度已存放在 COUNT单元 。
程序如下:
DATA SEGMENT
COUNT DW 20
NUM DW a1,a2,a3,….a20
MAX DW?
DATA ENDS
STACK SEGMENT PARA STACK ‘STACK’
DB 20DUP(?)
STACK ENDS
CODE SEGMENT
ASSUME CS,CODE,DS,DATA,SS,STACK
MAIN PROC FAR
PUSH DS
MOV AX,0
PUSH AX
MOV AX,DATA
MOV DS,AX
MOV BX,OFFSET NUM
MOV CX,COUNT
MOV AX,[BX]
INC BX
INC BX
LOOP1,CMP AX,[BX]
JAE LOOP2
MOV AX,[BX]
LOOP2,INC BX
INC BX
DEC CX
JNZ LOOP1
MOV [MAX],AX
RET
MAIN ENDP
CODE ENDS
END MAIN
【 例 4-7】 设计一个 100ms的软件延时程序 。 采用多重循环
程序, 内循环完成 10ms的延时, 外层循环 10次即可 。
程序如下:
CODE SENGMET
ASSUME CS,CODE
START,MOV DL,10
DELAY1,MOV CX,2800H
DELAY2,LOOP DELAY2
DEC DL
JNZ DELAY1
MOV AH,4CH
INT 21H
CODE ENDS
END START
§ 4.5子程序设计
1.子程序格式
子程序格式如下:
子程序名 PROC 类型
指令序列
子程序名 ENDP
2.子程序调用与返回
子程序调用与子程序返回由 CALL和 RET指令实现。
子程序调用方式有近程调用、远程调用、直接调用
和间接调用。
指令格式,CALL 子程序名
指令功能:这是调用子程序的指令 。 根据被调用的子
程序的类型不同, CALL指令的功能分为两种情况:
( 1) 近程调用 ( 段内调用 ), 类型为 NEAR,调用
时首先把当前 IP值压入堆栈, 而后执行子程序, 当子
程序执行完后, 利用 RET指令将堆栈中保护的 IP值弹
出 IP寄存器, 完成一次近程调用过程 。
( 2)远程调用(段间调用),类型为 FAR,调用时
先把 CS压入堆栈,再把 IP压入堆栈。尔后执行子程序,
当子程序执行完后,利用 RET指令堆栈中保护的程序
弹出 IP寄存器和 CS段寄存器中。完成一次远程的调用
过程。
3.保护现场和恢复现场
利用指令 PUSH保护现场, 利用指令 POP恢复现场 。
例如,SUB1 PROC NEAR
PUSH AX
保护现场 PUSH BX
PUSH CX
PUSH DX


POP DX
恢复现场 POP CX
POP BX
POP AX
RET
SUB1 ENDP
4.主程序和子程序之间的参数传送方法
主程序在调用子程序时, 经常需要传送一些参数给子程序;子
程序运行完后经常要回送一些信息给主程序 。 这种主程序和子
程序之间的信息传送称为参数传送的主要方法有以下几种:
( 1) 通用寄存器传送参数
例如:用寄存器 BX完成主程序 → 子程序的参数传送,并由子程
序将 BX带回 → 主程序。
主程序 子程序
MAIN,┇ SUBR PROC NEAR
┇ ┇
MOV DI,OFFSET DATA1 MOV AX,BX
MOV SI,OFFSET DATA2 ┇
MOV BX,[SI] 结果 →BX
CALL SUBR RET
MOV [DI],BX SUBR ENDP
( 2) 存储单元传送参数
若主程序和子程序在同一程序段中, 则子程序可直接访
问主程序数据段中的参数 。 换名说就是主程序和子程序
同时可访问同一数据段中的数据或地址 。
( 3) 通过堆栈传送参数
主程序与子程序传递参数时,可以把要传递的参数放在
堆栈中,这些参数既可以是数据,也可以是地址。具体
方法是在调用子程序前将参数送入堆栈,在子程序中通
过出栈方式取得参数,执行完毕后再将结果依次压入堆
栈。返回主程序后,通过出栈获得结果。