微机原理与接口技术汇编子程序涉及.docx
《微机原理与接口技术汇编子程序涉及.docx》由会员分享,可在线阅读,更多相关《微机原理与接口技术汇编子程序涉及.docx(16页珍藏版)》请在冰豆网上搜索。
微机原理与接口技术汇编子程序涉及
试验五汇编子程序设计
一、试验目的
(1)掌握汇编子程序设计的一般方法;
(2)掌握汇编子程序的调试方法;
(3)掌握递归子程序设计与调试方法。
二、输入输出子程序
1、十进制数输入子程序decibin
子程序名:
decibin
子程序功能:
用户输入十进制数放在BX中
入口参数:
无
出口参数:
BX存放输入的十进制数
受影响的寄存器:
AX、BX、CX、DX和标志寄存器
注意:
①用户输入字符‘0’~‘9’,当输入非法字符时结束输入,如回车;
②十进制数位数可以是1位、2位等,范围0~65535。
decibinprocnear
movbx,0
newchar:
movah,1
int21h
movdl,al
subal,30h
jlexit1
cmpal,9
jgexit1
cbw
xchgax,bx
movcx,10
mulcx
xchgax,bx
addbx,ax
jmpnewchar
exit1:
ret
decibinendp
2、十六进制数输入子程序hexibin
子程序名:
hexibin
子程序功能:
用户输入十六进制数放在BX中
入口参数:
无
出口参数:
bx存放输入的十六进制数
受影响的寄存器:
ax、bx、cx和标志寄存器
注意:
①用户输入0ah~0fh的数字时,输入大写字母‘A’~‘F’,小写字母‘a’~‘f’无效;
②子程序不能控制数的位数可能0位、1位、2位……等位数,如果输入位数大于4位,则以最新的4位十六进制数为准;
③输入字符可以按回车结束,当输入任何非法字符时也能结束数据输入。
hexibinprocnear
movbx,0
newchar:
movah,1
int21h
subal,30h
jlexit
cmpal,10
jladd_to
subal,7
cmpal,0ah
jlexit
cmpal,10h
jgeexit
add_to:
movcl,4
shlbx,cl
movah,0
addbx,ax
jmpnewchar
exit:
ret
hexibinendp
3、十进制数显示子程序binidec
子程序名:
binidec
子程序功能:
将bx寄存器存放的数以十进制的形式显示出来
入口参数:
bx存放要显示的数
出口参数:
无
受影响的寄存器:
ax、bx、cx、dx和标志寄存器
图5-1子程序binidec模块层次图
binidecprocnear
movcx,10000
calldec_div
movcx,1000
calldec_div
movcx,100
calldec_div
movcx,10
calldec_div
movcx,1
calldec_div
ret
binidecendp
dec_divprocnear
movax,bx
movdx,0
divcx
movbx,dx
movdl,al
adddl,30h
movah,2
int21h
ret
dec_divendp
4、十六进制数显示子程序binihex
子程序名:
binihex
子程序功能:
将di寄存器存放的数以十六进制的形式显示出来
入口参数:
di存放要显示的数
出口参数:
无
受影响的寄存器:
ax、bx、cx、dx和标志寄存器
注意:
显示十六进制数用到字符‘0’~‘9’和字符‘A’~‘F’,没有用到字符‘a’~‘f’。
binihexprocnear
movbx,4
lp:
movcl,4
roldi,cl
movdx,di
anddl,0fh
cmpdl,9
jbenext
adddl,07h
next:
adddl,30h
movah,2
int21h
decbx
jnzlp
movdl,'h'
movah,2
int21h
ret
binihexendp
5、二进制数显示子程序binshow
子程序名:
binshow
子程序功能:
将bx寄存器存放的数以二进制的形式显示出来
入口参数:
bx存放要显示的数
出口参数:
无
受影响的寄存器:
ax、bx、cx、dx和标志寄存器
binshowprocnear
movah,2
movcl,16
Again:
shlbx,1
jncnext
movdl,'1'
pushax
int21h
popax
jmpmm
Next:
movdl,'0'
pushax
int21h
popax
mm:
deccl
jnzagain
ret
binshowendp
三、示例
例5.1显示学生分数等级
编制一程序,要求接收从键盘输入的一个班级的学生成绩,并存放在50字的grade数组中。
然后根据grade中的学生成绩给出不同分数等级的学生人数,从终端中显示出来。
输入成绩用十进制,显示统计结果也用十进制数。
图5-2程序模块层次图
模块说明
1、分数输入子程序input
子程序名:
input
子程序功能:
用户输入若干十进制数,放在grade内存变量中
入口参数:
无
出口参数:
grade变量中存放输入若干数据;count变量中记录数据个数
受影响的寄存器:
ax、dx、si和标志寄存器
注意:
①由于数据存放在字单元中,范围0~65535,无符号数;
②数据间用逗号隔开,如87,75,95,63,90……如果用户输入87,回车,则子程序会出错,变量count统计的数据个数不对,注意逗号后一定跟上数据;
③若干数据输入以回车结束或非法字符结束,如果用户输入非法字符,给出'InputError!
'提示;
④定义变量gradedw50dup(?
)
countdw?
mess1db'Grade?
','$'
mess2db13,10,'InputError!
',13,10,'$'
⑤输入数据个数最多50个。
图5-3子程序input模块层次图
2、统计分数子程序rankp
子程序名:
rankp
子程序功能:
将内存中存放的分数按照<60、60∽69、70∽79、80∽89、90以上统计出来,存放在变量中
入口参数:
CX要统计分数的个数;BX指示统计分数的首地址
出口参数:
统计结果存放在变量s10、s9、s8、s7、s6、s5中
受影响的寄存器:
ax、bx、cx和标志寄存器
注意:
变量s10、s9、s8、s7、s6、s5的初值应为0
编程思路
根据题目的要求,程序可由三部分组成:
(1)输入:
以十进制的形式输入班级中的学生分数;
(2)统计:
根据不同的等级统计学生人数;
(3)输出:
显示统计结果,以十进制显示。
该例中明显的特色是子程序的调用,图5-2显示了子程序间嵌套调用的关系,一般复杂的程序都是由子程序嵌套调用完成的。
在设计每一个子程序中要明确子程序的功能、入口参数、出口参数,子程序运行时应该注意的细节,其中包括子程序实现中缺陷、程序结束的条件、数据输入的范围等。
外加还要清楚子程序中对寄存器的影响,必要的时候可以利用堆栈或者内存变量保存寄存器的值。
复杂的程序一般都由若干子程序嵌套调用,调用时的层次关系也应该好好设计。
调用子程序前一般要对入口参数进行设置,然后调用子程序。
在本例中,调用子程序rankp,完成对学生分数进行统计,入口参数bx指示存放学生分数变量grade的首地址,变量cx为分数的个数,指令语句如下:
leabx,grade
movcx,count
callrankp
参考程序清单
datareasegment
gradedw50dup(?
)
countdw?
s10dw0
s9dw0
s8dw0
s7dw0
s6dw0
s5dw0
mess1db'Grade?
','$'
mess2db13,10,'InputError!
',13,10,'$'
mess100db13,10,'100marknumber:
$'
mess90db13,10,'90marknumber:
$'
mess80db13,10,'80marknumber:
$'
mess70db13,10,'70marknumber:
$'
mess60db13,10,'60marknumber:
$'
mess50db13,10,'nopassnumber:
$'
datareaends
prognamsegment
mainprocfar
assumecs:
prognam,ds:
datarea
start:
movax,datarea
movds,ax
callinput
leabx,grade
movcx,count
callrankp
leadx,mess100
movah,09
int21h
movbx,s10
callbinidec
leadx,mess90
movah,09
int21h
movbx,s9
callbinidec
leadx,mess80
movah,09
int21h
movbx,s8
callbinidec
leadx,mess70
movah,09
int21h
movbx,s7
callbinidec
leadx,mess60
movah,09
int21h
movbx,s6
callbinidec
leadx,mess50
movah,09
int21h
movbx,s5
callbinidec
movah,4ch
int21h
mainendp
binidecprocnear
movcx,10000
calldec_div
movcx,1000
calldec_div
movcx,100
calldec_div
movcx,10
calldec_div
movcx,1
calldec_div
ret
binidecendp
dec_divprocnear
movax,bx
movdx,0
divcx
movbx,dx
movdl,al
adddl,30h
movah,2
int21h
ret
dec_divendp
inputprocnear
leadx,mess1
movah,09
int21h
movsi,0
movcount,0
enter:
calldecibin
inccount
cmpdl,','
jestore
cmpdl,13
jeexit2
jneerror
store:
movgrade[si],bx
addsi,2
jmpenter
error:
leadx,mess2
movah,09
int21h
exit2:
movgrade[si],bx
callcrlf
ret
inputendp
decibinprocnear
movbx,0
newchar:
movah,1
int21h
movdl,al
subal,30h
jlexit1
cmpal,9
jgexit1
cbw
xchgax,bx
movcx,10
mulcx
xchgax,bx
addbx,ax
jmpnewchar
exit1:
ret
decibinendp
rankpprocnear
compare:
movax,[bx]
cmpax,60
jlfive
cmpax,70
jlsix
cmpax,80
jlseven
cmpax,90
jleight
cmpax,100
jnenine
incs10
jmpchange_addr
nine:
incs9
jmpchange_addr
eight:
incs8
jmpchange_addr
seven:
incs7
jmpchange_addr
six:
incs6
jmpchange_addr
five:
incs5
change_addr:
addbx,2
loopcompare
ret
rankpendp
crlfprocnear
movdl,0ah
movah,02h
int21h
movdl,0dh
movah,02h
int21h
ret
crlfendp
prognamends
endstart
图5-4程序运行结果
程序调试
我们说一说由子程序构成的程序的调试过程。
图5-2可以看出主要由3个子模块构成,在input和rankp之间可以设置断点,在rankp和binidec之间可以设置断点。
图5-5是运行Debug时的情况,指令callinput的地址为0B90:
0005,下一条指令的偏移地址为0008h,执行命令-g8,完成input模块,分数放在内存中。
图5-6中可以看出刚才输入的12个成绩,count显示成绩个数,图中以十六进制给出,与用户十进制输入有些差别,注意转换。
此时说明第一块没有问题,如果出现差错,与用户输入内容不符,需要查看前一块。
再回到图5-5,设置第二个断点,运行-g13,查看寄存器和内存情况。
这样可以从整体对程序进行调试,使用的命令是-gxx命令,而不是逐条执行-t命令。
调试中第二点需要说明的是程序一般比较大,行数多,建议各个模块分别取出,建立源程序分别进行调试,确定正确性或进行修改。
我们将子程序binidec取出生成程序(图5-7),使用指令movbx,123,查看结果是否正确。
如果各个子程序都没有问题,再放在一起进行调试,注意下面几点:
入口参数、出口参数、子程序的局限性、标号之间重复。
总之,由子程序构成程序调试非常有特色,要经常实践!
图5-5程序运行Debug
图5-6程序运行Debug
图5-7调试子程序binidec