1、微机原理与接口技术汇编子程序涉及试验五 汇编子程序设计一、试验目的(1)掌握汇编子程序设计的一般方法;(2)掌握汇编子程序的调试方法;(3)掌握递归子程序设计与调试方法。二、输入输出子程序1、十进制数输入子程序decibin子程序名:decibin子程序功能:用户输入十进制数放在BX中入口参数:无出口参数:BX存放输入的十进制数受影响的寄存器:AX、BX、CX、DX和标志寄存器注意:用户输入字符09,当输入非法字符时结束输入,如回车;十进制数位数可以是1位、2位等,范围065535。decibin proc near mov bx , 0newchar: mov ah , 1 int 21h
2、mov dl , al sub al , 30h jl exit1 cmp al , 9 jg exit1 cbw xchg ax , bx mov cx , 10 mul cx xchg ax , bx add bx , ax jmp newcharexit1: retdecibin endp2、十六进制数输入子程序hexibin子程序名:hexibin子程序功能:用户输入十六进制数放在BX中入口参数:无出口参数:bx存放输入的十六进制数受影响的寄存器:ax、bx、cx和标志寄存器注意:用户输入0ah0fh的数字时,输入大写字母AF,小写字母af无效;子程序不能控制数的位数可能0位、1位、2
3、位等位数,如果输入位数大于4位,则以最新的4位十六进制数为准;输入字符可以按回车结束,当输入任何非法字符时也能结束数据输入。hexibin proc near mov bx , 0newchar: mov ah , 1 int 21h sub al , 30h jl exit cmp al , 10 jl add_to sub al , 7 cmp al , 0ah jl exit cmp al , 10h jge exitadd_to: mov cl , 4 shl bx , cl mov ah , 0 add bx , ax jmp newcharexit: rethexibin endp
4、3、十进制数显示子程序binidec子程序名:binidec子程序功能:将bx寄存器存放的数以十进制的形式显示出来入口参数:bx存放要显示的数出口参数:无受影响的寄存器:ax、bx、cx、dx和标志寄存器图5-1 子程序binidec模块层次图binidec proc nearmov cx , 10000call dec_divmov cx , 1000call dec_divmov cx , 100call dec_divmov cx , 10call dec_divmov cx , 1call dec_divretbinidec endpdec_div proc nearmov ax ,
5、bxmov dx , 0div cxmov bx , dxmov dl , aladd dl , 30hmov ah , 2int 21hretdec_div endp4、十六进制数显示子程序binihex子程序名:binihex子程序功能:将di寄存器存放的数以十六进制的形式显示出来入口参数:di存放要显示的数出口参数:无受影响的寄存器:ax、bx、cx、dx和标志寄存器注意:显示十六进制数用到字符09和字符AF,没有用到字符af。binihex proc near mov bx , 4lp: mov cl , 4 rol di , cl mov dx , di and dl , 0fh c
6、mp dl , 9 jbe next add dl , 07hnext: add dl , 30h mov ah , 2 int 21h dec bx jnz lp mov dl , h mov ah , 2 int 21h retbinihex endp5、二进制数显示子程序binshow子程序名:binshow子程序功能:将bx寄存器存放的数以二进制的形式显示出来入口参数:bx存放要显示的数出口参数:无受影响的寄存器:ax、bx、cx、dx和标志寄存器binshow proc near mov ah , 2 mov cl , 16Again: shl bx , 1 jnc next mov
7、 dl , 1 push ax int 21h pop ax jmp mmNext: mov dl , 0 push ax int 21h pop axmm: dec cl jnz again retbinshow endp三、示例例5.1 显示学生分数等级编制一程序,要求接收从键盘输入的一个班级的学生成绩,并存放在50字的grade数组中。然后根据grade中的学生成绩给出不同分数等级的学生人数,从终端中显示出来。输入成绩用十进制,显示统计结果也用十进制数。图5-2 程序模块层次图模块说明1、分数输入子程序input子程序名:input子程序功能:用户输入若干十进制数,放在grade内存变量
8、中入口参数:无出口参数:grade变量中存放输入若干数据;count变量中记录数据个数受影响的寄存器:ax、dx、si和标志寄存器注意:由于数据存放在字单元中,范围065535,无符号数;数据间用逗号隔开,如87,75,95,63,90如果用户输入87,回车,则子程序会出错,变量count统计的数据个数不对,注意逗号后一定跟上数据;若干数据输入以回车结束或非法字符结束,如果用户输入非法字符,给出Input Error!提示;定义变量 grade dw 50 dup(?) count dw ?mess1 db Grade?,$mess2 db 13,10,Input Error!,13,10,$
9、输入数据个数最多50个。图5-3 子程序input模块层次图2、统计分数子程序rankp子程序名:rankp子程序功能:将内存中存放的分数按照60、6069、7079、8089、90以上统计出来,存放在变量中入口参数:CX要统计分数的个数;BX指示统计分数的首地址出口参数:统计结果存放在变量s10、s9、s8、s7、s6、s5中受影响的寄存器:ax、bx、cx和标志寄存器注意:变量s10、s9、s8、s7、s6、s5的初值应为0编程思路根据题目的要求,程序可由三部分组成:(1)输入:以十进制的形式输入班级中的学生分数;(2)统计:根据不同的等级统计学生人数;(3)输出:显示统计结果,以十进制显
10、示。该例中明显的特色是子程序的调用,图5-2显示了子程序间嵌套调用的关系,一般复杂的程序都是由子程序嵌套调用完成的。在设计每一个子程序中要明确子程序的功能、入口参数、出口参数,子程序运行时应该注意的细节,其中包括子程序实现中缺陷、程序结束的条件、数据输入的范围等。外加还要清楚子程序中对寄存器的影响,必要的时候可以利用堆栈或者内存变量保存寄存器的值。复杂的程序一般都由若干子程序嵌套调用,调用时的层次关系也应该好好设计。调用子程序前一般要对入口参数进行设置,然后调用子程序。在本例中,调用子程序rankp,完成对学生分数进行统计,入口参数bx指示存放学生分数变量grade的首地址,变量cx为分数的个
11、数,指令语句如下:lea bx , grademov cx , countcall rankp参考程序清单datarea segment grade dw 50 dup(?) count dw ? s10 dw 0 s9 dw 0 s8 dw 0 s7 dw 0 s6 dw 0 s5 dw 0 mess1 db Grade?,$ mess2 db 13,10,Input Error!,13,10,$ mess100 db 13,10,100 mark number:$ mess90 db 13,10,90 mark number:$ mess80 db 13,10,80 mark number
12、:$ mess70 db 13,10,70 mark number:$ mess60 db 13,10,60 mark number:$ mess50 db 13,10,no pass number:$datarea endsprognam segmentmain proc far assume cs: prognam,ds:datareastart: mov ax , datarea mov ds , ax call input lea bx , grade mov cx , count call rankp lea dx , mess100 mov ah , 09 int 21h mov
13、bx , s10 call binidec lea dx , mess90 mov ah , 09 int 21h mov bx , s9 call binidec lea dx , mess80 mov ah , 09 int 21h mov bx , s8 call binidec lea dx , mess70 mov ah , 09 int 21h mov bx , s7 call binidec lea dx , mess60 mov ah , 09 int 21h mov bx , s6 call binidec lea dx , mess50 mov ah , 09 int 21
14、h mov bx , s5 call binidec mov ah , 4ch int 21hmain endpbinidec proc near mov cx , 10000 call dec_div mov cx , 1000 call dec_div mov cx , 100 call dec_div mov cx , 10 call dec_div mov cx , 1 call dec_div retbinidec endpdec_div proc near mov ax , bx mov dx , 0 div cx mov bx , dx mov dl , al add dl ,
15、30h mov ah , 2 int 21h retdec_div endpinput proc near lea dx , mess1 mov ah , 09 int 21h mov si , 0 mov count , 0enter: call decibin inc count cmp dl , , je store cmp dl , 13 je exit2 jne errorstore: mov gradesi ,bx add si , 2 jmp entererror: lea dx , mess2 mov ah , 09 int 21hexit2: mov gradesi ,bx
16、call crlf retinput endpdecibin proc near mov bx , 0newchar: mov ah , 1 int 21h mov dl , al sub al , 30h jl exit1 cmp al , 9 jg exit1 cbw xchg ax , bx mov cx , 10 mul cx xchg ax , bx add bx , ax jmp newcharexit1: retdecibin endprankp proc nearcompare: mov ax , bx cmp ax , 60 jl five cmp ax , 70 jl si
17、x cmp ax , 80 jl seven cmp ax , 90 jl eight cmp ax , 100 jne nine inc s10 jmp change_addrnine: inc s9 jmp change_addreight: inc s8 jmp change_addrseven: inc s7 jmp change_addrsix: inc s6 jmp change_addrfive: inc s5change_addr: add bx , 2 loop compare retrankp endpcrlf proc near mov dl , 0ah mov ah ,
18、 02h int 21h mov dl , 0dh mov ah , 02h int 21h retcrlf endpprognam ends end start图5-4 程序运行结果程序调试我们说一说由子程序构成的程序的调试过程。图5-2可以看出主要由3个子模块构成,在input和rankp之间可以设置断点,在rankp和binidec之间可以设置断点。图5-5是运行Debug时的情况,指令call input的地址为0B90:0005,下一条指令的偏移地址为0008h,执行命令-g8,完成input模块,分数放在内存中。图5-6中可以看出刚才输入的12个成绩,count显示成绩个数,图中以
19、十六进制给出,与用户十进制输入有些差别,注意转换。此时说明第一块没有问题,如果出现差错,与用户输入内容不符,需要查看前一块。再回到图5-5,设置第二个断点,运行-g13,查看寄存器和内存情况。这样可以从整体对程序进行调试,使用的命令是-gxx命令,而不是逐条执行-t命令。调试中第二点需要说明的是程序一般比较大,行数多,建议各个模块分别取出,建立源程序分别进行调试,确定正确性或进行修改。我们将子程序binidec取出生成程序(图5-7),使用指令mov bx ,123,查看结果是否正确。如果各个子程序都没有问题,再放在一起进行调试,注意下面几点:入口参数、出口参数、子程序的局限性、标号之间重复。总之,由子程序构成程序调试非常有特色,要经常实践!图5-5 程序运行Debug图5-6 程序运行Debug图5-7 调试子程序binidec
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1