这是《微机原理》这门课(2012下学期)的上机实验题目(2012.11.23完成)。初学汇编,对自己要求严格,尽量实现模块化,使程序简单易读。仅供初学者借鉴。
程序设计综合练习
一、 实验目的
1.增强和提高汇编语言程序设计的能力,掌握模块化程序设计的方法.
2.熟练掌握DOS常用功能的调用方法.
二、 实验仪器
586微机 一台
三、 实验内容
编写如下程序,并在机器上调试成功。程序采用菜单式选择,可以接收用户从键盘输入的五个命令(1-5),各命令功能分别为:
(1) 按下“1”键,完成字符串小写字母变成大写字母。
用户输入一由英文大小写字母或数字0-9组成的字符串(以回车结束),程序逐个检查字符串中各字符,将原串中小写字母变成大写字母,其他字符不变,并在屏幕上显示。用户按任一键,重做,按ESC键,返回主菜单。
(2) 按下“2”键,完成找最大值(二选一)。
a.接收用户输入的可显示字符串(以回车结束),程序将其中ASCII码值最大的字符显示出来;
b.接收用户输入若干个无符号8位数(以空格或逗号为分隔符,以回车结束),程序将其中最大的数显示出来。用户按任一键,重做,按ESC键,返回主菜单。
(3) 按下“3”键,完成排序(二选一)。
a.接收用户输入的可显示字符串,以回车结束。程序按ASCII码值大小由大到小排序并输出显示;
b.接收用户输入若干个有符号8位数(以空格或逗号为分隔符,以回车结束),程序将其中最大的数显示出来。用户按任一键,重做,按ESC键,返回主菜单。
(4) 按下“4”键,显示时间。
首先提示用户对时,即用户输入时、分、秒(以空格或逗号为分隔符,以回车结束),然后,在屏幕上不断显示时间,格式为:
XX(时): XX(分): XX(秒)
最好定点显示。用户按任一键,重新对时,按ESC键,返回主菜单。
(5) 按下“5”键,结束程序运行,返回系统提示符。
四、 源程序及流程
1. 流程图
系统流程图如下图1:
图1 多功能程序流程图
运行部分结果如下:
图2 程序运行主菜单
图3 程序子菜单1(小写转大写)
图4 程序子菜单4(时间显示)
图5 程序子菜单4(时间设置)
2. 源程序
;宏定义
;-------------------------------------------------------
;-------显示字符串-------
;-------------------------------------------------------
DISPL MACRO STR ;Function to display strings
PUSH DX
PUSH AX
LEA DX,STR
MOV AH,09H
INT 21H
POP AX
POP DX
ENDM
;-------------------------------------------------------
;-------判断用户是否选择继续-------
;-------------------------------------------------------
ISCONTINUE MACRO L ;Macro to judge whether to continue, L is a mark
DISPS 15,10,SMENU
MOV AH,08H
INT 21H
CMP AL,1BH
JNE L ;若用JE会导致编译,跳不了那么远
JMP MAIN
ENDM
;-------------------------------------------------------
;-----设置光标宏----
;-------------------------------------------------------
CURSOR MACRO CURX,CURY
PUSH AX
PUSH BX
PUSH DX ;DX必须保护,始终指向输入缓冲区
MOV AH,02H
MOV DH,CURX
MOV DL,CURY
MOV BH,0
INT 10H
POP DX
POP BX
POP AX
ENDM
;-------------------------------------------------------
;-----定位字符串显示宏------
;-------------------------------------------------------
DISPS MACRO X,Y,STR ;将STR的内容显示到X,Y的位置
PUSH AX
PUSH BX
PUSH DX
MOV AH,02H
MOV BH,00H ;显示页码,第0页
MOV DH,X ;行(X坐标)
MOV DL,Y ;列(Y坐标)
INT 10H
LEA DX,STR
MOV AH,09H
INT 21H
POP DX
POP BX
POP AX
ENDM
;-------------------------------------------------------
;--------清屏加色宏------
;-------------------------------------------------------
SCROLL MACRO N,ULR,ULC,LRR,LRC,ATT
PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV AH,06H
MOV AL,N ;N=上卷行数;N=0时,清窗口
MOV CH,ULR ;左上角行号(X)
MOV CL,ULC ;左上角列号(Y)
MOV DH,LRR ;右下角行号
MOV DL,LRC ;右下角列号
MOV BH,ATT ;卷入行属性,颜色设置
INT 10H
POP DX
POP CX
POP BX
POP AX
ENDM
;-------------------------------------------------------
;---------子程序预处理宏---------
;-------------------------------------------------------
PREP MACRO T ;预处理,显示子菜单标题(T),输入提示信息等
LEA SI,INBUF+1
LEA DI,OUTBUF
SCROLL 21,2,0,22,79,0FH ;清屏,内窗
DISPS 3,20,T ;显示子菜单标题(3行20列显示T)
DISPS 6,2,CAPION ;Prompt for a string to change
DISPS 8,2,INCAP ;Print "Your input is:"
MOV AH,0AH
INT 21H
MOV CH,0
MOV CL,[SI] ;获取输入字符串中,字符的个数
INC SI
ENDM
;-------------------------------------------------------
;---------堆栈段---------
;-------------------------------------------------------
STACK SEGMENT STACK 'STACK'
DB 100H DUP(?)
TOP LABEL WORD
STACK ENDS
;-------------------------------------------------------
;---------数据段---------
;-------------------------------------------------------
DATA SEGMENT
BASE DW MAIN,LTC,FMV,SORTS,STM,EXIT ;建立跳转表
WELCM DB 'Welcome to use this program!$'
MMENUI DB '---THIS PROGRAM IS DEVELOPED BY LiuZhi!---$'
MMENUD DB '--- 2012/10/28---$'
MMENUC DB 'Please Chose An Item,And Input The Number!$'
MMENU1 DB ' 1 -Lowercase Letters To Capital Letters$'
MMENU2 DB ' 2 -Find The Maximum Value$'
MMENU3 DB ' 3 -Sort$'
MMENU4 DB ' 4 -Set Time$'
MMENU5 DB ' 5 -Exit!$'
SMENU DB 'Press Any Key To Redo,Press "ESC" To Return To Main Menu!$'
WROCAP DB 'WRONG! You have press " " key! Please input a number between 1 and 5!$'
CAPION DB 'Please Input Your Strings and End With "Enter" Key!$'
INCAP DB 'Your Input Is: $'
INBUF DB 100
DB ?
DB 100 DUP(?)
OUTCAP DB ' My Output Is: $'
OUTBUF DB 100 DUP(?)
MAXCAP DB 'The char of max ASCII is: .$'
ERRINF DB 'ERROR! Please check the format you input!$'
TIMESETC DB 'Now,you can set the time! $'
TIMESETF DB 'Format:(01 25 32) or (01:25:32),and end with CR !$'
TIMESETS DB ' Succeed! $'
TDINV DB ' Invalid time data! Input again!$'
NODATCAP DB ' You have input nothing!$'
TIME DB 8 DUP (':'),12 DUP (' ');时间的底
DATA ENDS
;-------------------------------------------------------
;-------程序开始-------
;-------------------------------------------------------
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,ES:DATA,SS:STACK
START: MOV AX,DATA
MOV DS,AX
MOV ES,AX
MOV AX,STACK
MOV SS,AX
LEA SP,TOP
LEA DX,INBUF ;指向输入缓冲区
CLC
;-----欢迎界面 及主菜单------
MAIN: SCROLL 0,0,0,24,79,0 ;清屏
SCROLL 25,0,0,24,79,50H ;设置窗口颜色
SCROLL 21,2,0,22,79,0FH ;设置菜单颜色,黑底白字 //注意逗号应为半角字符,否则提示out of memory
DISPS 4,20,MMENUI ;Display the main menu
DISPS 6,30,MMENUD
DISPS 8,20,MMENUC
DISPS 10,20,MMENU1
DISPS 12,20,MMENU2
DISPS 14,20,MMENU3
DISPS 16,20,MMENU4
DISPS 18,20,MMENU5
ML: CURSOR 19,1DH
MOV AH,01H ;Recieve the choice
INT 21H
CMP AL,31H
JL ERROR
CMP AL,35H
JG ERROR
AND AX,00FH
LEA BX,BASE
SHL AL,1 ;将AL乘2,因为跳转表地址是dw类型的,
ADD BX,AX
JMP WORD PTR [BX]
;CMP AL,'1'
;JE LTC ;Choose 1,lowercase letter to capital letter
;CMP AL,'2'
;JE FMV ;Choose 2,find the maximum value
;CMP AL,'3'
;JE SORTS ;Choose 3,sort
;CMP AL,'4'
;JE STM ;Choose 4,show current time
;CMP AL,'5'
;JE EXIT ;Choose 5,exit the program
ERROR: CMP AL,0DH ;如果是回车的话,赋CR
JE MCR
MOV [WROCAP+23],AL ;Other char
MOV [WROCAP+24],' '
JMP D
MCR: MOV WORD PTR [WROCAP+23],'RC'
D: DISPS 20,5,WROCAP ;Show the wrong information
JMP ML
LTC: CALL LLTOCL
ISCONTINUE LTC
FMV: CALL FMAXV
ISCONTINUE FMV
SORTS: CALL SORT
ISCONTINUE SORTS
STM: CALL SHOWTIME
ISCONTINUE STM
EXIT: SCROLL 0,0,0,24,79,0 ;清屏
MOV AH,4CH ;Exit.
INT 21H
;-------------------------------------------------------
;------Process: lowercase letter to capital letter.-----
;-------------------------------------------------------
LLTOCL PROC
REFLASHL:PREP MMENU1 ;显示子菜单
CMP CL,0 ;若输入为空则跳转至REDO
JE REFLASHL
LL1: MOV AL,[SI]
CMP AL,'a'
JB MTOB ;NO CHANGE
CMP AL,'z'
JA MTOB
SUB AL,20H ;Convert
MTOB: MOV [DI],AL
INC SI
INC DI
LOOP LL1
MOV BYTE PTR [DI],'$'
DISPS 10,2,OUTCAP
DISPS 10,17,OUTBUF
RET
LLTOCL ENDP
;-------------------------------------------------------
;----Process: find the maximum value.------
;-------------------------------------------------------
FMAXV PROC
PUSH BX
REFLASHF:PREP MMENU2 ;显示子菜单
CMP CL,0 ;若输入为空则跳转至REDO
JE REFLASHF
MOV AL,0
FL1: CMP AL,[SI]
JA NEXT
MOV AL,[SI]
NEXT: INC SI
LOOP FL1
MOV [MAXCAP+26],AL
DISPS 10,2,MAXCAP
POP BX
RET
FMAXV ENDP
;-------------------------------------------------------
;-------Process: sort.----------
;-------------------------------------------------------
SORT PROC
PREP MMENU3 ;显示子菜单标题(T),输入提示信息等
DEC CX
ADD SI,CX
MOV BYTE PTR [SI+1],'$'
LP1: PUSH CX
PUSH SI
LP2:
MOV AL,[SI]
CMP AL,[SI-1]
JBE NOXCHG
XCHG AL,[SI-1]
MOV [SI],AL
NOXCHG: DEC SI
LOOP LP2
POP SI
POP CX
LOOP LP1
DISPS 10,2,OUTCAP
DISPS 10,17,INBUF[2] ;显示排序结果
RET
SORT ENDP
;-------------------------------------------------------
;---------Process: show current time.---------
;-------------------------------------------------------
SHOWTIME PROC
SCROLL 21,2,0,22,79,0FH 清屏,内窗
DISPS 3,20,MMENU4
DISPS 5,25,TIMESETC
DISPS 7,15,TIMESETF
SHOW: MOV SI,0
MOV BL,100
DIV BL
MOV AH,2CH ;GET TIME
INT 21H
MOV AL,CH ;HOUR
CALL BCDASC ;要转换的在AL中
INC SI
MOV AL,CL ;MINUTE
CALL BCDASC
INC SI
MOV AL,DH
CALL BCDASC ;要转换的在AL中
MOV BP,OFFSET TIME ;使用int 10H的13H号功能,在Teletype模式下显示字符串(BP为地址)
MOV DX,0A22H ;DX为行列(DH,DL)
MOV CX,8 ;CX为显示字符串长度
MOV BX,004EH ;BH:页码,BL:属性
MOV AX,1301H ;AL:显示输出方式,1—字符串中只含显示字符,显示后,光标位置改变
INT 10H
MOV AH,02H ;设置光标位置
MOV DX,0A22H
MOV BH,0
INT 10H
MOV BX,0018H ;延时用(外层),若不延时,光标会在时间左右来回跑!
RE: MOV CX,0FFFFH
REA: LOOP REA
DEC BX
JNZ RE ;
MOV AH,01H ;检测是否有字符输入,ZF=1:无
INT 16H
JE SHOW
CALL SETTIME ;设置时间子程序
RET
SHOWTIME ENDP
;-------------------------------------------------------
;-------------设置时间子程序----------
;-------------------------------------------------------
SETTIME PROC
PUSH DX
MOV AH, 0AH ; 输入时间串
LEA DX, INBUF
INT 21H
CMP INBUF[1],0
JE NODAT
MOV BL, 10
MOV AL, INBUF + 2
SUB AL, '0'
MUL BL
ADD AL, INBUF + 3
SUB AL, '0'
CMP AL, 0
JB INVALID
CMP AL, 24
JAE INVALID ; 判断 时 有效性
MOV CH, AL
MOV AL, INBUF + 5
SUB AL, '0'
MUL BL
ADD AL, INBUF + 6
SUB AL, '0'
CMP AL, 0
JB INVALID
CMP AL, 60
JAE INVALID ; 判断 分 有效性
MOV CL, AL
MOV AL, INBUF + 8
SUB AL, '0'
MUL BL
ADD AL, INBUF + 9
SUB AL, '0'
CMP AL, 0
JB INVALID
CMP AL, 60
JAE INVALID ; 判断 秒 有效性
MOV DH, AL
MOV DL, 0
MOV AH, 2DH
INT 21H ; 置系统时间
DISPS 12,20,TIMESETS ;设置成功
JMP RETURN
NODAT: DISPS 12,20,NODATCAP
JMP RETURN
INVALID:DISPS 12,20,TDINV ;时间数据无效
RETURN: POP DX
RET
SETTIME ENDP
;-------------------------------------------------------
;------Process:时间数值转换成ASCII码字符子程序,要转换的在AL中,调用前赋好值------
;-------------------------------------------------------
BCDASC PROC NEAR
PUSH BX
CBW
MOV BL,10
DIV BL
ADD AL,30H
MOV TIME[SI],AL
INC SI
ADD AH,30H
MOV TIME[SI],AH
INC SI
POP BX
RET
BCDASC ENDP
;------结束!------
CODE ENDS
END START
五、 实验体会
1. 要熟练掌握8086汇编指令,包括寻址方式,指令格式等等;
2. 在编程实现阶段,汇编时提示跳转不到的问题,根据错误提示可知是条件转移指令的问题,因为它所跳的范围在-127~+128字节,因而改用了“跳转表”来实现主程序至子程序的跳转;
3. INT 21H中断提供的功能有限,为使程序界面友好美观,操作简便,在实现时调用了INT 10H中断,程序中使用的中断见附录;
4. 编写汇编程序,给人的感觉是不断地把数据从一个地方搬到另一个地方,再加上一些对数据的处理,所以,画出流程图再编程,可加快速度,另外最好有个汇编指令详表,遇到不清楚的可随手查,如此,可加深记忆与加快开发的速度。
附录
程序中用到的INT 10H 中断:
1. 02H
功能:用文本坐标下设置光标位置
入口参数:AH=02H
BH=显示页码
DH=行(Y坐标)
DL=列(X坐标)
出口参数: 无
2. 06H和07H
功能:初始化屏幕或滚屏
入口参数:AH=06H—向上滚屏,07H—向下滚屏
AL=滚动行数(0—清窗口)
BH=空白区域的缺省属性
(CH、CL)=窗口的左上角位置(Y坐标,X坐标)
(DH、DL)=窗口的右下角位置(Y坐标,X坐标)
出口参数: 无
3. 13H
功能:在Teletype模式下显示字符串
入口参数:AH=13H
BH=页码
BL=属性(若AL=00H或01H)
CX=显示字符串长度
(DH、DL)=坐标(行、列)
ES:BP=显示字符串的地址 AL= 显示输出方式
0—字符串中只含显示字符,其显示属性在BL中。显示后,光标位置不变
1—字符串中只含显示字符,其显示属性在BL中。显示后,光标位置改变
2—字符串中含显示字符和显示属性。显示后,光标位置不变
3—字符串中含显示字符和显示属性。显示后,光标位置改变
出口参数: 无。