3.8.1 程序设计步骤
在这里,我们不去涉及软件工程的具体问题,只简单介绍程序设计的入门知识。 一般可以按下面的步骤进行: (1) 仔细了解问题的要求。 (2) 制定方案。 (3) 编写程序。 (4) 查错。 (5) 测试。 (6) 形成文件。
3.8.2 程序设计的基本方法
1.顺序程序 也有人称之为简单程序,它确实是程序中最简单的形式。这种程序CPU执行时,是以指令的排列顺序逐条执行的。 若m,n,w分别为三个8位无符号数,现欲求Q=m×n-w。若m,n,w存放在当前DS所决定数据段、偏移地址为DATA的顺序单元中,而且Q可放在AX中,则程序为 LEA SI,DATA MOV AL[SI] MOV BL,[SI+1] MUL BL MOV BX,0 MOV BL,[SI+2] SUB AX,BX HLT 2. 分枝程序 分枝程序的基本结构如图3.20所示。由图3.20可见,分枝程序的基本思路就是判断条件A是否成立,若成立,则执行P -1;若不成立,则执行P -2。 现举例说明如下: 从接口03F0H中取数,若此数≥90,则将00H送接口03F7H;若此数<90,则将FFH送接口03F7H。 程序如下: MOV DX,03F0H IN AL,DX CMP AL,90 JNC NEXT1 MOV AL,0FFH JMP NEXT2 NEXT1:MOV AL,00H NEXT2:MOV DX,03F7H OUT DX,AL HLT
例:在DS数据段偏移地址为DATA开始的顺序80个单元中,存放着某班80个同学的微型机原理考试成绩。现欲编程序统计≥90分、89分~70分,69分~60分和<60分的人
数,并将统计的结果放在当前数据段偏移地址为BUFFER的顺序单元中。
程序如下:
MOV DX,0000H
MOV BX,0000H
MOV CX,80
LEA SI,DATA
LEA DI,BUFFERGOON:MOV AL,[SI]
CMP AL,90
JC NEXT3
INC DH
JMP STOR
NEXT3:CMP AL,70
JC NEXT5
INC DL
JMP STOR
NEXT5: CMP AL,60
JC NEXT7
INC BH
JMP STOR
NEXT7:INC BL
STOR: INC SI
LOOP GOON
MOV [DI],DH
MOV[DI+1],DL
MOV[DI+2],BH
MOV[DI+3],BL
HLT
3. 循环程序 循环程序是强制CPU重复执行某一指令集合的一种程序结构。它可以使许多重复性工作的程序大为简化。 循环程序通常有两种结构方式,如图3.22(a)和(b)所示。 在内存40000H开始的顺序30个单元中存放着8位无符号数,若将它们的和放在DX中,试编程序。 程序如下: MOV AX,4000H MOV DS,AX MOV SI,0000H MOV CX,30 XOR AX,AX GOON:ADD AL,[SI] ADC AH,00H INC SI DEC CX JNZ GOON MOV DX,AX HLT
在图3.22中所画的是单一的循环。在解决问题中还会出现二重循环甚至多重循环的情况。只要单一循环的概念清楚,二重及多重循环也就容易解决。 在此仅以简单的例子加以说明。
例:在DS所决定的数据段,从偏移地址BUFFER开始顺序存放100个无符号16位数。现欲编写程序将这100个字按大小顺序排序。 程序如下: LEA DI,BUFFER MOV BL,99 NEXT0:MOV SI,DI MOV CL,BL NEXT3:MOV AX,[SI] ADD SI,2 CMP AX,[SI] JNC NEXT5 MOV DX,[SI] MOV[SI-2],DX MOV[SI], AX NEXT5:DEC CL JNZ NEXT3 DEC BL JNZ NEXT0 HLT
4. 子程序 使用子程序时应注意的几个问题: (1)子程序如何调用和如何返回。 (2)子程序的入口条件(或称入口信息)和出口条件(出口信息)。 (3)子程序中使用了哪些寄存器,调用之前是否需要保护。 (4)其他诸如占内存多少、执行时间长短、影响哪些标志、出错如何处理等。 在此我们只直接用来定义一个通过查询向接口输出数据的输出子程序: SENDAT PROC FAR PUSH AX PUSH DX PUSH SI LEA SI,BUFR GOON:MOV DX,03FBH WAIT: IN AL,DX TEST AL,20H JZ WAIT MOV AL,[SI] MOV DX,03F8H OUT DX,AL INC SI CMP AL,0AH JNE GOON POP SI POP DX POP AX RET SENDAT ENDP主程序在调用子程序时,一方面初始数据要传递给子程序,另一方面子程序的运行结果要传递给主程序。尽管没有初始数据或没有运行 结果的情况也有,但一般情况下我们必须予以考虑。 参数传递可用以下3种方式: ·利用寄存器 ·利用内存单元 ·利用堆栈
5.表
在微型计算机应用中,经常用到表的运算。例如,温度传 感器的一个温度对应输出一个电压,温度值与电压之间如果有 较复杂的函数关系,那么要计算出某一电压(假定
用10位二进 制数表示)的温度值往往要进行复杂运算。 例如,在当前数据段(DS所决定)偏移地址为TABLE开始的顺序 单元中存放着用一个字(16位二进制数)所表示的温
度值,此表 按顺序对应温度传感器电压值的10位二进制值:000H到3FFH。若 在当前数据段偏移地址为DATAB的顺序单元中已存放着温度电压 值的10位编码。试编程
序将其转换成实际的温度值,放回原存贮 单元。 程序如下: START: LEA SI,TABLE MOV AX,DATAB ADD SI,AX MOV AX,[SI] MOV DATAB,AX HLT
下面我们分别对这两种功能调用作一简要介绍。
(1) 高级功能调用(DOS功能调用) (2) 低级功能调用 (3) 功能调用实例
例1 带显示的键盘输入子程序KSDIN。功能:接收从键盘输入的一个字符并在显示器上显示该字符。 输入:从键盘输入一个ASCII码字符。 输出:输入字符送缓冲区,并显示该字符。 KSDIN PROC NEAR MO VAH,1;置功能号 INT 21H;输入结果放AL中 MOV IN BUFF,AL;输入字符送缓冲区 RET KSDIN ENOP
例2 设置系统日期的子程序SETTIME。 功能:将变量YEAR、MONTH、DAY的内容作为时间设置系统日期。 SETTIME PROC NEAR MOV AH,2BH ;置功能号 MOV CX,YEAR ;置年参数(字) MOV DH,MONTH;置月参数(字节) MOV DL,DAY;置日参数(字节) INT 21H; OR AL,AL;检查状态 JNZ ERROR;日期无效转… RET ERROR:… RET …YEAR DW0 MONTH DB0 DAY DB0 SETTIME ENDP
例3 用户程序终止返回DOS。 功能:用户程序结束返回DOS操作系统。 PROEND:MOV AH,0 ;置功能号 INT 21H ;返回操作系统 例4 置CRT显示方式子程序SETCRT。 功能:根据不同类型码设置不同的显示方式。 若本系统显示卡为EGA卡,现要将显示器设置成640×200、彩色16色图形方式。 SETCRT PROC NEAR MOV AH,0 ;设置功能类型 MOV AL,0EH;设置调用参数 INT10H ;调BIOS功能 RET SETCRT ENDP 例5 写一个字符到指定通信口子程序WCOMI。 功能:将缓冲区BUFF中的字符送串行通信口输出。 输入:要发送的字符放于缓冲区BUFF。 输出:将缓冲区字符送COMI串行口输出。 WCOMI PROC NEAR MOV AH,01H;功能1为写字符 MOV AL,BUFF;字符送AL MOV DX,0;用COM1通信口发送 INT 14H;调用BIOS功能 RET WCOMI ENDP