【 本章重点 】 熟练掌握汇编语言的四种程序设计方法: ...
description
Transcript of 【 本章重点 】 熟练掌握汇编语言的四种程序设计方法: ...
【本章重点】熟练掌握汇编语言的四种程序设计方法:
顺序程序设计,分支程序设计,循环程序
设计以及子程序设计。
【本章难点】确定算法,合理分配内存工作单元。
第 4 章 汇编语言程序设计
§4.1 汇编语言程序设计概述
4.1.1 汇编语言程序设计步骤
使用汇编语言设计一个程序大致上可分为以下几个步骤。
(1) 分析问题,明确要求。解决问题之前,首先要明确所要解决的问题和要达到的目的、技术指标等。
(2) 确定算法。根据实际问题的要求、给出的条件及特点,找出规律性,最后确定所采用的计算公式和计算方法,这就是一般所说的算法。算法是进行程序设计的依据,它决定了程序的正确性和程序的指令。
(3) 画程序流程图,用图解来描述和说明解题步骤。
(4) 分配内存工作单元,确定程序与数据区的存放地址。
(5) 编写源程序。
(6) 程序优化。
( 7 )程序调试、修改和最后确定源程序。只有通过上机调试并得出正确结果的程序,才能认为是正确的程序。没有调试过的程序,很难保证程序无错误,程序调试是不可缺省的。
§4.2顺序程序设计对于一些简单的数据处理,只要把完成处理的各个步骤用汇编语言描述清楚,让计算机按指令编写的次序从头到尾一条条执行即可,这样的程序结构称为顺序结构。
【例 4-1 】已知 X 和 Y 是数据段中的两个无符号字节单元,用程序完成表达式 Z= ( X2 + Y2 ) /2 的计算。
编制程序如下:
DATA SEGMENTX DB 15Y DB 34Z DW ?
DATA ENDSCODE SEGMENT
ASSUME CS : CODE , DS : DATASTART: MOV AX , DATA
MOV DS , AX ;初始化数据段MOV AL , X ; X 中的内容送 ALMUL AL ;计算 X×XMOV BX , AX ; X×X 乘积送 BXMOV AL , Y ; Y 中的内容送 ALMUL AL ;计算 Y×YADD AX , BX ;计算 X2 + Y2
SHR AX , 1 ;计算( X2 + Y2 ) /2MOV Z , AX ;结果送 Z 单元MOV AH , 4CHINT 21H ;返回 DOS
CODE ENDSEND 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 , 1INT 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 , 2MOV DL , 13INT 21H ;回车MOV DL , 10INT 21H ;换行MOV DL , BLMOV AH , 2INT 21H ;输出十位数MOV DL , BHINT 21H ;输出个位数MOV AH , 4CHINT 21H ;返回 DOS
CODE ENDSEND 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
(( 22)存储单元传送参数)存储单元传送参数
若主程序和子程序在同一程序段中,则子程序可直接访问主程序数据段中的参数。换名说就是主程序和子程序同时可访问同一数据段中的数据或地址。
(( 33)通过堆栈传送参数)通过堆栈传送参数
主程序与子程序传递参数时,可以把要传递的参数放在堆栈中,这些参数既可以是数据,也可以是地址。具体方法是在调用子程序前将参数送入堆栈,在子程序中通过出栈方式取得参数,执行完毕后再将结果依次压入堆栈。返回主程序后,通过出栈获得结果。