前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【汇编】微机原理与接口技术课程设计

【汇编】微机原理与接口技术课程设计

作者头像
zstar
发布于 2022-06-14 07:10:10
发布于 2022-06-14 07:10:10
1K00
代码可运行
举报
文章被收录于专栏:往期博文往期博文
运行总次数:0
代码可运行

本文是微机原理与接口技术课程设计 完整的程序和实验报告可在此处下载:https://gitee.com/zstar1003/xdu-homework/tree/master/%E5%BE%AE%E6%9C%BA%E5%8E%9F%E7%90%86

一、题目要求

编写程序实现下列5项功能,通过从键盘输入1~5进行菜单式选择。 (1) 按数字键“1”,完成将字符串中的小写字母变换成大写字母。用户输入由英文大小写字母或数字0~9组成的字符串(以回车结束),变换后按下列格式在屏幕上显示:

<原字符串>:abcdgyt0092 <新字符串>:ABCDGYT0092 按任意键重做;按Esc键返回主菜单

(2) 按数字键“2”,完成在字符中找最大值。用户输入由英文大小写字母或数字0~9组成的字符串(以回车结束),找出最大值后按下列格式在屏幕上显示:

<原字符串>The maximum is <最大值>. 按任意键重做;按Esc键返回主菜单。

(3) 按数字键“3”,完成输入数据组的排序。用户输入一组十进制数值(小于255),然后变换成十六进制数,并按递增方式进行排序,按下列格式在屏幕上显示:

<原数值串> <新数值串> 按任意键重做;按Esc键返回主菜单。

(4) 按数字键“4”,完成时间的显示。在屏幕的右上角实时显示出时间HH:MM:SS。 按任意键重做;按Esc键返回主菜单。

(5) 按数字键“5”,结束程序的运行,返回操作系统。

二、实验环境

2.1 软件环境

操作系统:Windows10 编辑器:emu8086

2.2 硬件环境

CPU:i7-10750H RAM:32GB

三、问题分析

3.1 功能一分析

功能一要求完成字符串大小写的转换,同时需输出原字符串和处理后的字符串。对功能进行分解,需要完成以下几个子任务: (1) 键盘字符的读取和存储 (2) 异常输入的检测 (3) 字符串的显示 (4) 大小写的转换

3.2 功能二分析

功能二要求在字符中找最大值,同时需输出原字符串和字符中的最大值。对功能进行分解,需要完成以下几个子任务: (1) 键盘字符的读取和存储 (2) 异常输入的检测 (3) 字符串的显示 (4) 比较字符并记录字符最大值

3.3 功能三分析

功能三要求将输入的十进制数转换成十六进制数输出,并对这些数按递增方式进行排序输出。对功能进行分解,需要完成以下几个子任务: (1) 键盘字符的读取和存储 (2) 异常输入的检测 (3) 字符串的显示 (4) 十进制数转换成十六进制数 (5) 输入数据的递增排序

3.4 功能四分析

功能四要求将获取系统当前时间,并将该时间显示在屏幕的右上角。对功能进行分解,需要完成以下两个子任务: (1) 系统时间的获取 (2) 时间位置的确定

3.5 功能五分析

功能五要求结束程序的运行,返回操作系统。该功能实现较为简单,通过DOS的中断调用即可实现。

四、解决方法

4.1 整体设计和基本功能

4.1.1 实验整体设计

本实验采用的是交互式的程序设计,即初始化为一个菜单,可以根据用户的输入分别选择5项功能。同时,当每一项功能结束时,用户可以选择重新尝试或者返回主菜单。 具体的流程如下图所示:

4.1.2 获取用户的输入

总体流程中以及各个子任务中都需获取用户的输入并进行存储,这项功能的实现使用了DOS的中断调用。由于其需频繁使用,因此在程序中,将其封装成宏定义函数get_char,其功能是获取单个输入字符并存储在AL中。 相关代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
get_char macro  
    MOV    AH,1  
    INT    21h  
endm  

4.1.3 异常输入的检测

在每次获取用户输入后,都需要对输入数据进行检测,若输入异常值则需要提示错误信息并使用户重新输入。 例如,在主菜单中,用户的输入只能为1-5,输入其他值会报错,该部分可由下面的代码实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CMP    AL,31h  
JB     main_input_error  
CMP    AL,35h  
JA     main_input_error  
JMP    select 

由于字符在计算机中使用ASCII码来进行存储。因此使用CMP指令,将输入字符的ASCII码和目标字符的ASCII码进行比较。其中31h为数字“1”的ASCII码,35h为数字“5”的ASCII码。若输入字符的ASCII码小于31h或大于35h,则跳转到错误提示代码块(main_input_error),否则进入选择代码块(select)。

4.1.4 字符串的显示

在程序中,提示字符串与处理结果的字符串都需要进行显示。由于这项功能也需要被频繁使用,因此在程序中将其封装为宏定义函数print_string,相关代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
print_string macro string  
    LEA    DX,string  
    MOV    AH,09h  
    INT    21h  
endm

该函数的传入参数为string,通过DOS的中断调用,可以在屏幕上显示出DS:DX地址处的字符串。

4.1.5 换行显示功能

在程序运行中,为了使显示界面更为美观,需要频繁使用换行显示的功能,因此在程序中也将其封装为宏定义函数,相关代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
print_line macro  
    MOV    AH,2      ;调用2号功能系统,将DL的内容显示到屏幕  
    MOV    DL,0DH    ;0DH是回车符的ASCIIINT    21h  
    MOV    AH,2  
    MOV    DL,0AH    ;0AH是换行符的ASCIIINT    21h  
endm   

换行的本质是打印出一串空行,这里通过显示回车符和换行符的方式实现换行这一效果。

4.2 功能一:字符串小写转大写

在问题分析中,明确了功能一需要完成以下四个子任务: (1) 键盘字符的读取和存储 (2) 异常输入的检测 (3) 字符串的显示 (4) 大小写的转换 其中,前三个子任务已经在宏定义中实现,因此本功能只要完成第四个任务。 考虑到字符在计算机中是以ASCII码的方式进行存储,而大小写字母之间的ASCII码相差20H,因此,只需将所有小写字母的ASCII码减去20H,即可转换成大写字母。 核心代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cmp_data:   
    ;CL用来记录剩余的处理字符数量,若CL无空值,直接跳出     
    CMP    CL,00h      
    JE     task1_finish  
    MOV    AL,[SI]  
    ;只有小写字母才进行转换,若不是小写字母直接输出  
    CMP    AL,61h  
    JB     cmp_data_finish  
    SUB    AL,20h    ;小写转大写:小写字母-20H  
      
cmp_data_finish:  
    ;[DI]用来存储处理后的字符数据  
    MOV    [DI],AL  
    INC    SI  
    DEC    CL ;处理完一个字符,CL-1   
    INC    DI   
    ;CL不为0,代表没处理完  
    JMP    cmp_data  

其中,CL用来记录剩余的处理字符数量,SI为原字符存储的变址索引,DI为处理后的字符存储的变址索引。 功能一的流程图如下所示:

4.3 功能二:在字符中找最大值

在问题分析中,明确了功能二需要完成以下四个子任务: (1) 键盘字符的读取和存储 (2) 异常输入的检测 (3) 字符串的显示 (4) 比较字符并记录字符最大值 其中,前三个子任务已经在宏定义中实现,因此本功能只要完成第四个任务。 本程序采用遍历的思路进行比较。在获取每个字符之后,通过源变址寄存器SI对原字符串进行遍历,比较每个字符的ASCII码,初始化最大值为第一个字符,若后面的存在字符比当前最大值大,则最大值替换为该字符。最后,对源字符串和目标字符结尾加入字符串结束标记“$”,调用宏定义函数进行输出。 比较过程的核心代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func_2_cmp_data:  
    ;假如已经遍历完毕则进行跳出      
    CMP    CL,00h      
    JE     func2_finish  
    MOV    AL,[SI]  
    MOV    AH,[DI]  
    ;假如AL>AH,进行跳转,将AL的值存入[DI],即最大值  
    CMP    AL,AH  
    JA     func_2_cmp_data_finish     ;JA:无符号大于则跳转  
    INC    SI  
    DEC    CL  
    JMP    func_2_cmp_data  

功能二的流程图如下所示:

4.4 功能三:输入数据组的排序

在问题分析中,明确了功能三需要完成以下五个子任务: (1) 键盘字符的读取和存储 (2) 异常输入的检测 (3) 字符串的显示 (4) 十进制数转换成十六进制数 (5) 输入数据的递增排序 其中,前三个子任务已经在宏定义中实现,因此本功能只要完成后两个任务。

4.4.1 十进制数转换成十六进制数

考虑到用户输入的数字在计算机内部存储为ASCII码,因此第一步必须将ASCII码转换成十进制数。数字“0”的ASCII码为30H,因此将输入的0-9的ASCII码-30H即可提取到对应的十进制数,也可以将0-9的ASCII码的高位清零,直接获得对应的十进制数。高位清零操作可以用当前数据和OFH取逻辑与来实现。 实际上,寄存器是以十六进制来进行数据的存储,因此当数字仅有一位时,十六进制和十进制完全一样。因此只需考虑多位数据的情况。这一功能中,不同的数据采用空格进行分隔,在检测到空格之前,每一个数据先进行存储,当存在下一位数据时,之间的数据*10再加上下一位数据,这样就实现了十进制数向十六进制数的转换。 相关代码如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
MOV    DL,0   
MOV    DH,10    
task_3_real_store:  
    get_char  
    CMP    AL,0DH   ;判断是否按下回车键   
    JE     task3_next_step  
    CMP    AL,20H   ;判断是否按下空格键   
    JE     task3_save_num    
    ;小于0或大于9跳转报错  
    CMP    AL,30H ;30H为"0"ASCIIJB     task3_error_input  
    CMP    AL,39H ;39H为"9"ASCIIJA     task3_error_input   
    MOV    BH,0        
    ;这里首先需要将ASCII码转换成十进制数,0ASCII码为30H,因此可以用ASCII-30H或者将高位清零  
    AND    AL,0FH ;4位清零   
    MOV    BL,AL  
    MOV    AL,DL  
    MUL    DH     ;每一个高位*10  
    ADD    AX,BX  
    MOV    DL,AL   
    JMP    task_3_real_store 

4.4.2 输入数据的递增排序

为了将输入数据进行递增排序,本程序运用了双层循环的选择排序方法。 相关代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
sort:   
    LEA    SI,string_task3_count  
    MOV    CL,[SI]  
    LEA    SI,string_task3       
;外循环  
fori:  
    LEA    DI,string_task3_count   
    MOV    CH,CL  
    MOV    DI,SI  
    INC    DI    
;内循环   
forj:  
    MOV    BL,[SI]      
    MOV    BH,[DI]  
    CMP    BL,BH                                     
    JBE    afterswap  
    MOV    [SI],BH  
    MOV    [DI],BL      
afterswap:  
    DEC    CH  
    INC    DI  
    CMP    CH,1  
    JA     forj   
    INC    SI  
    DEC    CL  
    CMP    CL,1                                 
    JA     fori  

第i轮外循环,BL指向原字符串第i个字符,外循环的次数由CH来确定。第j轮内循环,BH指向原字符串第j个字符,j初始值为i+1,内循环的次数由CL来确定。每一次内循环中,第i个字符分别与其后面的字符一一比较,若BL>BH,则进行两数交换。第一次外循环确定第一位最小值,第二次外循环确定第二位最小值,直到所有位置的最小都确定,从而实现递增排序。 功能三的流程图如下所示:

4.5 功能四:右上角显示系统时间

在问题分析中,明确了功能四需要完成以下两个子任务: (1) 系统时间的获取 (2) 时间位置的确定

4.5.1 系统时间的获取

本程序使用DOS中断INT 21H的2CH号功能来获取当前系统时间,小时值会存放在CH中,分值会存放在CL中,秒值会存放在DH中。 相关代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
MOV AH,2Ch     ;CH=,CL=,DH=INT 21h   

4.5.2 时间位置的确定

本程序使用DOS中断INT 10H的2H号功能来设置光标显示在右上角。其中,DH代表行号,DL代表列号。 相关代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
MOV DH,0  ;行号      
MOV DL,72  ;列号    
MOV BH,0    
MOV AH,2     
INT 10h   

4.6 功能五:结束程序的运行

本程序使用DOS中断INT 21H的4CH号功能来实现结束程序运行。 相关代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
MOV AH, 4CH  
INT 21h  

五、遇到的问题及调试

5.1 问题一:代码冗长问题

在编程中,遇到重复的代码多次使用导致整体代码冗长的问题,例如字符获取、字符显示、换行等操作,需使用重复的代码。 解决方法:通过宏定义的方式将重复用到的代码进行封装,从而大大减小代码冗余量。

5.2 问题二:程序错误问题

在编写功能三的时候,初次运行时,递增后的字符和输入的字符不相同。 解决方法:通过调试,发现错误原因是在功能三中,使用了DL寄存输入的字符数据,而在中途使用换行语句时,调用了INT 21H的2号功能,导致DL发生变化。因此,在换行前后通过入栈出栈的方式来保护DL数值,从而使问题得到解决。

六、程序运行效果

下面是各个功能的运行效果截图。 6.1 功能一运行效果

6.2 功能二运行效果

6.3 功能三运行效果

6.4 功能四运行效果

七、完整程序

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1.	DATAS SEGMENT     
2.	    ;此处输入数据段代码   
3.	    string_main db 'plase input the function number (1~5)$'  
4.	    tip DB 'please input string:','$'  
5.	    string_task2_result2 db 'The maximum is :$'  
6.	    string_error db 'Wrong number, please input again. $'  
7.	    string_task3_info db 'please input the DECimAL numbers:',0DH,0AH,'$'    
8.	    again_or_return db 'What do you want to do next" Main Menu or Redo"[ESC/any other key]: $'  
9.	    task1_info db 'Now, we are doing fuction 1: $'   
10.	    task2_info db 'Now, we are doing fuction 2: $'   
11.	    task3_info db 'Now, we are doing fuction 3: $'   
12.	    ; emu8086不支持dup(?) 因此用0来初始化  
13.	    string_task1 db 100 dup(0)  
14.	    string_task1_result db 100 dup(0)  
15.	    string_task2 db 100 dup(0)    
16.	    string_task2_result db 10 dup(0)       
17.	    string_task3 db 100 dup(0)   
18.	    string_task3_count db 10 dup(0)  
19.	    string_task3_result db 100 dup(0)             
20.	    hour db 0  
21.	    minute db 0  
22.	    second db 0  
23.	    time db "00:00:00$"    
24.	    len equ $-time  
25.	    num db 0     
26.	  
27.	DATAS ENDS  
28.	  
29.	STACKS SEGMENT  
30.	    TOP LABEL WORD  
31.	    ;此处输入堆栈段代码   
32.	    DW      100H    DUP(0)  
33.	STACKS ENDS           
34.	  
35.	;换行   
36.	print_line macro  
37.	    MOV    AH,2      ;调用2号功能系统,将DL的内容显示到屏幕  
38.	    MOV    DL,0DH    ;0DH是回车符的ASCII39.	    INT    21h  
40.	    MOV    AH,2  
41.	    MOV    DL,0AH    ;0AH是换行符的ASCII42.	    INT    21h  
43.	endm         
44.	  
45.	;调用DOS功能,该功能为显示DSDX地址处的字符     
46.	print_string macro string  
47.	    LEA    DX,string  
48.	    MOV    AH,09h  
49.	    INT    21h  
50.	endm    
51.	  
52.	;用来获取单个输入字符     
53.	get_char macro  
54.	    MOV    AH,1  
55.	    INT    21h  
56.	endm  
57.	            
58.	CODES SEGMENT  
59.	    ASSUME CS:CODES,DS:DATAS,SS:STACKS  
60.	START:  
61.	    MOV AX,DATAS  
62.	    MOV DS,AX       
63.	      
64.	menu:  
65.	    print_string string_main  
66.	    get_char     
67.	    ;只能输入1-5  
68.	    CMP    AL,31h  
69.	    JB     main_input_error  
70.	    CMP    AL,35h  
71.	    JA     main_input_error  
72.	    JMP    select  
73.	      
74.	main_input_error:  
75.	    print_line  
76.	    print_string string_error      
77.	    print_line  
78.	    JMP    menu      
79.	      
80.	select:      
81.	     CMP   AL,31h  
82.	     JE    Task1  
83.	     CMP   AL,32h  
84.	     JE    Task2  
85.	     CMP   AL,33h  
86.	     JE    Task3  
87.	     CMP   AL,34h  
88.	     JE    Task4  
89.	     CMP   AL,35h  
90.	     JE    Task5  
91.	   
92.	return_menu:  
93.	     print_line  
94.	     JMP    menu       
95.	  
96.	;任务一:实现小写转化成大写  
97.	Task1 PROC  
98.	    print_line   
99.	    print_line   
100.	    print_string task1_info  
101.	    print_line   
102.	    print_string tip  
103.	    LEA    SI,string_task1  
104.	    MOV    CL,00H;CL用来存储需要处理字符的数量,初始化置0             
105.	      
106.	restore_input:      
107.	    get_char  
108.	    MOV    BL,AL  ;BL用来存储输入的字符信息,保护数据  
109.	    ;假如当前字符输入是回车(0DH),则不进行存储,直接跳出  
110.	    CMP    AL,0DH  
111.	    JE     deal_first   
112.	    ;对空格字符进行存储,单独判断  
113.	    CMP    AL,20H ;20H为"空格"ASCII114.	    JE     real_store    
115.	    ;设置输入字符的范围,只能存储数字、大小写字母,否则报错       
116.	    CMP    AL,30H ;30H为"0"ASCII117.	    JB     input_error  
118.	    CMP    AL,39H ;39H为"9"ASCII119.	    JBE    real_store  
120.	    CMP    AL,41H ;41H为"A"ASCII121.	    JB     input_error  
122.	    CMP    AL,5AH ;5AH为"Z"ASCII123.	    JBE    real_store  
124.	    CMP    AL,61H ;61H为"a"ASCII125.	    JB     input_error      
126.	    CMP    AL,7AH ;7AH为"z"ASCII127.	    JBE    real_store      
128.	      
129.	;错误跳转信息,并重新提示输入    
130.	input_error:  
131.	    print_line  
132.	    print_string string_error  
133.	    print_line  
134.	    print_string tip  
135.	    LEA    SI,string_task1  
136.	    MOV    CL,00H;CL用来存储需要处理字符的数量,初始化置0    
137.	    JMP    restore_input  
138.	  
139.	;存储当前字符     
140.	real_store:       
141.	    MOV    AL,BL ;BL存储的字符重新赋值给AL  
142.	    MOV    [SI],AL ;AL存储的字符传输到[SI]进行存储  
143.	    INC    SI  
144.	    INC    CL  
145.	    INC    DI   
146.	    ;未检测到结束标志“回车”,返回上一步继续存储下一个字符  
147.	    JMP    restore_input  
148.	  
149.	;重新回到存储的首地址位置,对每一个字符进行处理      
150.	deal_first:      
151.	    LEA    SI,string_task1  
152.	    LEA    DI,string_task1_result  
153.	      
154.	cmp_data:   
155.	    ;CL用来记录剩余的处理字符数量,若CL无空值,直接跳出     
156.	    CMP    CL,00h      
157.	    JE     task1_finish  
158.	    MOV    AL,[SI]  
159.	    ;只有小写字母才进行转换,若不是小写字母直接输出  
160.	    CMP    AL,61h  
161.	    JB     cmp_data_finish  
162.	    SUB    AL,20h    ;小写转大写:小写字母-20H  
163.	      
164.	cmp_data_finish:  
165.	    ;[DI]用来存储处理后的字符数据  
166.	    MOV    [DI],AL  
167.	    INC    SI  
168.	    DEC    CL ;处理完一个字符,CL-1   
169.	    INC    DI   
170.	    ;CL不为0,代表没处理完  
171.	    JMP    cmp_data  
172.	      
173.	task1_finish:  
174.	    print_line   
175.	    ;为输入和输出字符串添加结束标志  
176.	    MOV    [SI],'$'      
177.	    MOV    [DI],'$'   
178.	    ;这里显示输入  
179.	    print_string string_task1  
180.	    print_line             
181.	    ;这里显示输出结果  
182.	    print_string string_task1_result  
183.	    print_line  
184.	      
185.	    ;判断返回菜单或者重试  
186.	    print_string again_or_return      
187.	    get_char  
188.	    CMP    AL,1BH   ;判断是否按下esc   
189.	    JE     return_menu    
190.	  
191.	    JMP    Task1     
192.	  
193.	Task1 ENDP  
194.	  
195.	;任务二:在字符中找最大值  
196.	Task2 PROC     
197.	    print_line   
198.	    print_line   
199.	    print_string task2_info  
200.	    print_line   
201.	    print_string tip  
202.	    LEA    SI,string_task2  
203.	    MOV    CL,00H;CL用来存储需要处理字符的数量,初始化置0   
204.	      
205.	task_2_restore_input:      
206.	    get_char  
207.	    MOV    BL,AL  ;BL用来存储输入的字符信息,保护数据  
208.	    ;假如当前字符输入是回车(0DH),则不进行存储,直接跳出  
209.	    CMP    AL,0DH  
210.	    JE     task2_dealfirst   
211.	      
212.	     ;设置输入字符的范围,只能存储数字、大小写字母,否则报错       
213.	    CMP    AL,30H ;30H为"0"ASCII214.	    JB     task2_input_error  
215.	    CMP    AL,39H ;39H为"9"ASCII216.	    JBE    task2_store  
217.	    CMP    AL,41H ;41H为"A"ASCII218.	    JB     task2_input_error  
219.	    CMP    AL,5AH ;5AH为"Z"ASCII220.	    JBE    task2_store  
221.	    CMP    AL,61H ;61H为"a"ASCII222.	    JB     task2_input_error      
223.	    CMP    AL,7AH ;7AH为"z"ASCII224.	    JBE    task2_store     
225.	              
226.	task2_store:  
227.	    MOV    AL,BL  
228.	    MOV    [SI],AL  
229.	    INC    SI  
230.	    INC    CL  
231.	    JMP    task_2_restore_input   
232.	   
233.	;错误跳转信息,并重新提示输入    
234.	task2_input_error:  
235.	    print_line  
236.	    print_string string_error  
237.	    print_line  
238.	    print_string tip   
239.	    JMP    Task2  
240.	      
241.	task2_dealfirst:      
242.	    LEA    SI,string_task2  
243.	    LEA    DI,string_task2_result      
244.	    MOV    AL,[SI]  
245.	    MOV    [DI],AL   ;[DI]用来存储输入的数据  
246.	    INC    SI  
247.	    DEC    CL  
248.	      
249.	;遍历比较      
250.	func_2_cmp_data:  
251.	    ;假如已经遍历完毕则进行跳出      
252.	    CMP    CL,00h      
253.	    JE     func2_finish  
254.	    MOV    AL,[SI]  
255.	    MOV    AH,[DI]  
256.	    ;假如AL>AH,进行跳转,将AL的值存入[DI],即最大值  
257.	    CMP    AL,AH  
258.	    JA     func_2_cmp_data_finish     ;JA:无符号大于则跳转  
259.	    INC    SI  
260.	    DEC    CL  
261.	    JMP    func_2_cmp_data  
262.	      
263.	func_2_cmp_data_finish:  
264.	    MOV    [DI],AL  
265.	    INC    SI  
266.	    DEC    CL  
267.	    JMP    func_2_cmp_data  
268.	      
269.	func2_finish:  
270.	    print_line  
271.	    MOV    [SI],'$'  
272.	    INC    DI      
273.	    MOV    [DI],'$'  
274.	    ;先输出原字符串     
275.	    print_string string_task2  
276.	    ;补一个空格进行分隔  
277.	    MOV    DL,20h  
278.	    MOV    AH,2  
279.	    INT    21H   
280.	    print_string string_task2_result2 ;the maximum is :$  
281.	    print_string string_task2_result  
282.	    print_line  
283.	      
284.	    ;判断返回菜单或者重试  
285.	    print_string again_or_return      
286.	    get_char  
287.	    CMP    AL,1BH   ;判断是否按下esc   
288.	    JE     return_menu   
289.	  
290.	    JMP    Task2    
291.	  
292.	Task2 ENDP  
293.	   
294.	;任务三:输入数据组的排序  
295.	Task3 PROC   
296.	    print_line   
297.	    print_line   
298.	    print_string task3_info  
299.	    print_line       
300.	    print_string string_task3_info     
301.	    LEA    SI,string_task3  
302.	    MOV    CL,0  
303.	    MOV    BH,0      
304.	    MOV    DI,0    
305.	        
306.	task3_store:      
307.	    MOV    DL,0   
308.	    MOV    DH,10    
309.	      
310.	task_3_real_store:  
311.	    get_char  
312.	    CMP    AL,0DH   ;判断是否按下回车键   
313.	    JE     task3_next_step  
314.	    CMP    AL,20H   ;判断是否按下空格键   
315.	    JE     task3_save_num    
316.	    ;小于0或大于9跳转报错  
317.	    CMP    AL,30H ;30H为"0"ASCII318.	    JB     task3_error_input  
319.	    CMP    AL,39H ;39H为"9"ASCII320.	    JA     task3_error_input   
321.	    MOV    BH,0        
322.	    ;这里首先需要将ASCII码转换成十进制数,0ASCII码为30H,因此可以用ASCII-30H或者将高位清零  
323.	    AND    AL,0FH ;4位清零   
324.	    MOV    BL,AL  
325.	    MOV    AL,DL  
326.	    MUL    DH     ;每一个高位*10  
327.	    ADD    AX,BX  
328.	    MOV    DL,AL   
329.	    JMP    task_3_real_store   
330.	      
331.	task3_error_input:   
332.	    print_line  
333.	    print_string string_error     
334.	    JMP    Task3  
335.	  
336.	;检测到空格则进行一次数值保存   
337.	task3_save_num:      
338.	    CMP    BH,0  
339.	    JNZ    task3_before_store  
340.	    MOV    [SI],DL  
341.	    INC    SI  
342.	    INC    CL    
343.	      
344.	task3_before_store:      
345.	    MOV    BH,1  
346.	    JMP    task3_store       
347.	  
348.	;输出回车之后      
349.	task3_next_step:  
350.	    ;注意,换行会改变DL数值,因此必须用堆栈保护DL,栈仅能对字节进行操作  
351.	    PUSH   DX   
352.	    print_line  
353.	    POP    DX  
354.	    MOV    [SI],DL   
355.	    INC    SI  
356.	    INC    CL  
357.	    LEA    DI,string_task3_count  
358.	    MOV    [DI],CL  
359.	  
360.	task3_finish:  
361.	    LEA    DI,string_task3_count  
362.	    MOV    CL,[DI]      
363.	          
364.	    LEA    DI,string_task3  
365.	    PUSH   DX   
366.	    print_line  
367.	    POP    DX  
368.	  
369.	;将十六进制数转换成ASCII码显示输出   
370.	task3_write:     
371.	    MOV    BH,[DI]  
372.	    MOV    DL,BH  
373.	    AND    DL,0F0H ;低位清零  
374.	    SHR    DL,4    ;逻辑右移,将DL右移4375.	    CMP    DL,0AH  
376.	    JGE    task3_writehighchar  
377.	    ADD    DL,30H  ;数值0-9要进行显示需转换成ASCII码,需+30H  
378.	    JMP    task3_writehigh    
379.	  
380.	;用来写当前十六进制数的高位      
381.	task3_writehighchar:  
382.	    ADD    DL,37H  ;数值A-F要进行显示需转换成ASCII码,需+37H     
383.	      
384.	task3_writehigh:  
385.	    MOV    AH,2  
386.	    INT    21H  
387.	    MOV    DL,BH  
388.	    AND    DL,00FH ;高位清零    
389.	    CMP    DL,0AH  
390.	    JGE    task3_writelowchar    ;JGE大于等于  
391.	    ADD    DL,30H  
392.	    JMP    task3_writelow   
393.	      
394.	;写当前十六进制数的低位      
395.	task3_writelowchar:  
396.	    ADD    DL,37H       
397.	        
398.	task3_writelow:   
399.	       
400.	    MOV    AH,2  
401.	    INT    21H     
402.	    ;每输出一个十六进制数在后面添加H标识  
403.	    MOV    DL,48H  
404.	    MOV    AH,2  
405.	    INT    21H     
406.	    ;每输出一个十六进制数显示空格进行分隔  
407.	    MOV    DL,20h  
408.	    MOV    AH,2  
409.	    INT    21H      
410.	       
411.	    INC    DI  
412.	    DEC    CL  
413.	    CMP    CL,0   ;CL记录剩余处理的字符数量,假如不为0,继续跳转运行  
414.	    JNE    task3_write  
415.	   
416.	;采用选择排序实现十六进制从小到大输出  
417.	;BL用来存储第i位,BH用来存储第i+1,i+2,i+3...位,每次外循环确定第i位最小值  
418.	sort:   
419.	    LEA    SI,string_task3_count  
420.	    MOV    CL,[SI]  
421.	    LEA    SI,string_task3     
422.	      
423.	;外循环  
424.	fori:  
425.	    LEA    DI,string_task3_count   
426.	    MOV    CH,CL  
427.	    MOV    DI,SI  
428.	    INC    DI    
429.	;内循环   
430.	forj:  
431.	    MOV    BL,[SI]      
432.	    MOV    BH,[DI]  
433.	    CMP    BL,BH                                     
434.	    JBE    afterswap  
435.	    MOV    [SI],BH  
436.	    MOV    [DI],BL      
437.	      
438.	afterswap:  
439.	    DEC    CH  
440.	    INC    DI  
441.	    CMP    CH,1  
442.	    JA     forj  
443.	      
444.	    INC    SI  
445.	    DEC    CL  
446.	    CMP    CL,1                                 
447.	    JA     fori  
448.	               
449.	task3_finish2:  
450.	    LEA    DI,string_task3_count  
451.	    MOV    CL,[DI]      
452.	    LEA    DI,string_task3  
453.	    PUSH   DX   
454.	    print_line  
455.	    POP    DX  
456.	      
457.	;输出排序后的结果      
458.	task3_write2:     
459.	    MOV    BH,[DI]  
460.	    MOV    DL,BH  
461.	    AND    DL,0F0H ;低位清零  
462.	    SHR    DL,4    ;逻辑右移,将DL右移4463.	    CMP    DL,0AH  
464.	    JGE    task3_writehighchar2  
465.	    ADD    DL,30H  ;数值0-9要进行显示需转换成ASCII码,需+30H  
466.	    JMP    task3_writehigh2    
467.	  
468.	task3_writehighchar2:  
469.	    ADD    DL,37H  ;数值A-F要进行显示需转换成ASCII码,需+37H     
470.	      
471.	task3_writehigh2:  
472.	    MOV    AH,2  
473.	    INT    21H  
474.	    MOV    DL,BH  
475.	    AND    DL,00FH ;高位清零    
476.	    CMP    DL,0AH  
477.	    JGE    task3_writelowchar2    ;JGE大于等于  
478.	    ADD    DL,30H  
479.	    JMP    task3_writelow2   
480.	      
481.	;写当前十六进制数的低位      
482.	task3_writelowchar2:  
483.	    ADD    DL,37H       
484.	        
485.	task3_writelow2:    
486.	    MOV    AH,2  
487.	    INT    21H      
488.	    ;每输出一个十六进制数在后面添加H标识  
489.	    MOV    DL,48H  
490.	    MOV    AH,2  
491.	    INT    21H     
492.	    ;每输出一个十六进制数显示空格进行分隔  
493.	    MOV    DL,20h  
494.	    MOV    AH,2  
495.	    INT    21H          
496.	    INC    DI  
497.	    DEC    CL  
498.	    CMP    CL,0             ;CL记录剩余处理的字符数量,假如不为0,继续跳转运行  
499.	    JNE    task3_write2     
500.	       
501.	    PUSH   DX   
502.	    print_line  
503.	    POP    DX   
504.	    ;判断返回菜单或者重试  
505.	    print_string again_or_return      
506.	    get_char  
507.	    CMP    AL,1BH   ;判断是否按下esc   
508.	    JE     return_menu   
509.	  
510.	    JMP    Task3   
511.	               
512.	Task3 ENDP  
513.	  
514.	  
515.	;任务四:输出系统时间到屏幕右上角  
516.	Task4 PROC     
517.	;首先对窗口清屏      
518.	clear:      
519.	    MOV AX,CS  
520.	    MOV SS,AX  
521.	    MOV SP,0x7c00  ;set stack and SP  
522.	  
523.	    MOV AH,0x06  
524.	    MOV AL,0  
525.	  
526.	    MOV CH,0  ;(0,0)  
527.	    MOV CL,0  
528.	    MOV DH,24  ;(24,79)  
529.	    MOV DL,79  
530.	    MOV BH,0x07 ;黑底白字  
531.	    INT 0x10  
532.	  
533.	;设置光标位置   
534.	setshow:      
535.	    MOV DH,0  ;行号      
536.	    MOV DL,72  ;列号    
537.	    MOV BH,0  
538.	    ;置光标位置  
539.	    MOV AH,2     
540.	    INT 10h     
541.	  
542.	;获取系统时间  
543.	get_system_time:   
544.	    ;获取时间  
545.	    MOV AH,2Ch     ;CH=,CL=,DH=546.	    INT 21h           
547.	    MOV hour,CH  
548.	    MOV minute,CL  
549.	    MOV second,DH      
550.	    ;时间显示到字符串  
551.	    MOV AX,0        
552.	    MOV AL,hour     ;:AL,余数:AH  
553.	    MOV num,10  
554.	    DIV num  
555.	    ADD AL,30h  
556.	    MOV time[0],AL  
557.	    ADD AH,30h  
558.	    MOV time[1],AH   
559.	      
560.	    MOV AX,0  
561.	    MOV AL,minute  
562.	    MOV num,10  
563.	    DIV num  
564.	    ADD AL,30h  
565.	    MOV time[3],AL  
566.	    ADD AH,30h  
567.	    MOV time[4],AH  
568.	      
569.	    MOV AX,0  
570.	    MOV AL,second  
571.	    MOV num,10  
572.	    DIV num  
573.	    ADD AL,30h  
574.	    MOV time[6],AL  
575.	    ADD AH,30h  
576.	    MOV time[7],AH  
577.	      
578.	    ;输出系统时间  
579.	    LEA DX, time  
580.	    MOV AH, 9     
581.	    INT 21h    
582.	  
583.	    ;判断返回菜单或者重试  
584.	    print_string again_or_return      
585.	    get_char  
586.	    CMP    AL,1BH   ;判断是否按下esc   
587.	    JE     return_menu   
588.	  
589.	    JMP    setshow   
590.	  
591.	Task4 ENDP  
592.	   
593.	   
594.	;任务五:退出   
595.	Task5 PROC  
596.	    MOV AH, 4CH  
597.	    INT 21h  
598.	Task5 ENDP      
599.	      
600.	CODES ENDS  
601.	    END START  
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-05-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
DOS子程序汇编样例及详解
1、P和T都是执行,像这个语句add ax,bx ,你不管用哪个,都是执行这一句,但如果是call next 这个next是一个程序段,那么就不一样了,用P,直接就把这段程序执行完了,用T则进入内部一句一句的执行.这个和C语言的那些调试一样,有的进入函数内部,有的就执行完函数。
timerring
2022/08/03
7760
DOS子程序汇编样例及详解
汇编语言从键盘输入一个字符串以十进制输出字符串中非字母字符的个数A to Z)
(1)从键盘输入一个字符串(串长不大于80)。 (2)以十进制输出字符串中非字母字符的个数(不是a to z或 A to Z)。 (3)输出原字符串且令非字母字符闪烁显示。 (4)找出字符串中ASCII码值最大的字符,在字符串中用红色显示。 (5)字符串的输入和结果的输出都要有必要的提示,且提示独占一行。 (6)要使用到子程序。 data segment hintinput db "please input a string:$" hintoutput1 db "The number of n
炒香菇的书呆子
2021/05/27
3.2K0
DOS汇编程序提高练习
编写一个汇编程序,实现字符串的复制功能,并且将复制的字符串显示出来。(选做部分:倒
timerring
2022/07/20
9220
DOS汇编程序提高练习
使用BIOS进行键盘输入【编程:字符串的输入】
;=======字符串的输入========= ;功能: ; 1、在输入的同时显示这个字符串 ; 2、在输入回车符后,字符串输入结束 ; 3、能够删除已经输入的字符 ; ;字符串的入栈、出栈、显示 ;参数说明: ; 1、(ah)=功能号, ; 0表示入栈 ; 1表示出栈 ; 2表示显示 ; 2、ds:si指向字符栈空间 ; 3、 对于0号功能:(al)=入栈字符 ; 对于1号功能:(al)=返回的字符 ; 对于2号功能:(dh)、(dl)=字符串在屏幕上显示的行、列位置
全栈程序员站长
2022/07/05
1.1K0
《汇编语言》课程设计2
jz指令:https://zhidao.baidu.com/question/564008138.html
Hk_Mayfly
2019/07/30
8470
【微机原理与汇编语言】实验三 码制转换实验
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
韩旭051
2019/11/08
1.6K0
汇编笔记
1)、MOV BL, CX: 可行但mov的源比目标长度大,会导致数据丢失。警告:Operand types must match
饶文津
2020/06/02
2.2K0
《汇编语言》课程设计2
jz指令:https://zhidao.baidu.com/question/564008138.html
Hk_Mayfly
2019/07/30
6900
汇编(从键盘接收若干个 N 位的十进制数值(0~65535),并以不同进制显示其和。)
从键盘接收若干个 N 位的十进制数值(0~65535),并以二进制、十进制、十六进制三种数制形式显示其和。
用户9372190
2022/01/10
8370
DOS汇编分支、循环编程与寄存器分析
整个代码的逻辑是先逐位比较,先比较高位数据,比较完后直接输出高位,再比较低位的,比较完后输出低位。其中比较的规则为:因为是十六进制的数,有十个数字和六个字母组成。首先进行数字的比较,小于等于9 的直接输出数字。但对于大于9 的数字,由于ASCII码最小的字母A 和数字9 的ASCII 码相差了7,因此需要加7进行转换,再进行显示。
timerring
2022/07/20
8900
DOS汇编分支、循环编程与寄存器分析
汇编版冒泡排序
用到的东西都很简单,只用了基本的寄存器和jmp运算。 更新补充:我自己的电脑上\n即可实现回车换行,但是有的机器不支持,需要\r\n才可以回车换行。如果测试时出现没有回车的情况,可以在对应部分的输出语句加上mov dl,13 int 21h。
KevinBruce
2020/03/11
3450
使用汇编语言编写的计算器
计算器实现简单的加减乘除运算(小于65536的正数) ①从键盘输入算数的等式 ②不接受复合算数如3+5*7 ③按‘=’号输出结果 ④按‘C’号作为CLEAR清零 程序分为输入模块,判断模块,计算模块,
里克贝斯
2021/05/21
1K0
使用汇编语言编写的计算器
8086汇编实现对数字的存储、输出
QQ20181230-173338@2x.png 目标 设计一个INPUT子程序,使其能够接收用户输入的数字(以字符串的形式),并将数字存储到AX寄存器。 设计一个DECOUT/BINOUT/HEXOUT子程序,使他们能够以十进制/二进制/十六机制的形式将AX中的数字输出到屏幕上。 分析 对于INPUT子程序,我们需要调用DOS功能接收用户输入的字符串,将ASCII码转为数字,再依次乘以10、100...由于CPU执行指令时会占用AX,我们将积的累加和存储在内存变量中,最后一步复制到AX中。 对于DECO
gojam
2019/05/14
3K0
雷军 1994 年写的代码,像诗一样优雅!不服不行!
雷军曾自夸自己写的代码像诗一样优雅,网友感觉这雷军写的94年代码如何?2019年世界500强企业排行榜,仅成立9年的小米全球排名第468位,这让小米的创始人雷军兴奋的像个孩子一样。雷军一高兴就给小米的每一位员工包了1000股公司的股票,总价值超过了一亿。
路人甲Java
2020/06/04
4.4K0
汇编指令大全
 80×86指令系统,指令按功能可分为以下七个部分。   (1) 数据传送指令。   (2) 算术运算指令。   (3) 逻辑运算指令。   (4) 串操作指令。   (5) 控制转移指令。   (6) 处理器控制指令。   (7) 保护方式指令。 3.3.1数据传送指令   数据传送指令包括:通用数据传送指令、地址传送指令、标志寄存器传送指令、符号扩展指令、扩展传送指令等。   一、通用数据传送指令   1传送指令   传送指令是使用最频繁的指令,格式:MOV DEST,SRC   功能:把一个字节,字或双字从源操作数SRC传送至目的操作数DEST。   传送指令允许的数据流方向见图311。
全栈程序员站长
2022/09/06
1.6K0
Mac下写8086汇编
我们课上讲的是8086下的16位汇编,如此远古的操作系统导致我在配置环境时遇到了很多问题。起初打算在win7虚拟机下用masm和汇编ide写汇编,但编译不成功,因为masm新版已经不是16位了。据查,masm5.0版本支持16位汇编,但又发现了DOSBox,与其在win7虚拟机下模拟DOS,不如直接在Mac中运行DOS环境。
gojam
2019/05/14
2.7K0
汇编语言、与C语言、实现--汉诺塔--
   用汇编语言实现汉诺塔。只需要显示移盘次序,不必显示所移盘的大小,例如: X>Z,X>Y,Z>Y,X>Z,....。
书童小二
2018/09/03
1.7K0
汇编语言、与C语言、实现--汉诺塔--
x86汇编语言之8086语法和指令集
上面使用db或者dw定义数据的方式,定义数据的同时就已经定义好了数据所在的物理地址, 如果我们想要从指定的内存地址中写入或者读取数据的话,需要借助段寄存器来实现 在8086中给我们提供了DS SS CS ES四个寄存器,理论上你使用哪一个都行,但是由于系统默认读取DS寄存器中的数据当做段地址,所以我们一般使用DS进行数据的段地址管理
乱码三千
2021/08/24
2.7K0
大学课程 | 《微机原理与接口技术》笔记
数据定义伪指令(1)用于定义数据区中变量的类型及其所占内存空间大小(2)DB(Define Byte):定义的变量为字节型(3)DW (Define Word) :定义的变量为字类型(4)DD (Define Double Word) :定义的变量为双字型(5)DQ (Define Quadword) :定义的变量为4字型(6)DT (Define Tenbytes) :定义的变量为10字节型
Justlovesmile
2021/12/14
4.1K0
大学课程 | 《微机原理与接口技术》笔记
汇编基础
​ cup与所有内存之间:地址总线,数据总线,控制总线,每条线对应不同信息,指令与数据分开
Dean0731
2020/08/17
1.5K0
相关推荐
DOS子程序汇编样例及详解
更多 >
LV.1
这个人很懒,什么都没有留下~
作者相关精选
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验