山东大学汇编语言上机实验实验五.docx
《山东大学汇编语言上机实验实验五.docx》由会员分享,可在线阅读,更多相关《山东大学汇编语言上机实验实验五.docx(41页珍藏版)》请在冰豆网上搜索。
山东大学汇编语言上机实验实验五
子程序设计
2.6显示学生名次表rank
编制一个程序,要求接受键盘输入的一个班的学生成绩,并存放于一个50字的grade数组中,其中grade+i保存学号为I+1的学生成绩。
然后根据grade中的学生成绩,把学生成绩依次填入50字的rank数组中,其中rank+i的内容是学号为i+1的学生的名次。
再按学号顺序把名次从终端上显示出来。
本题要做的主要工作和例2.2的内容是完全一样的,只是增加了由用户键入学生成绩及输出学生名次两个部分的内容,因此这三个部分可以用子程序结构来完成。
子程序结构划分的层次图如图2.17所示,可以看出,main为主要模块,其下一层的三个模块为程序的三大部分。
现将各模块说明如下:
1.模块名:
main为总模块
输入:
从键盘输入一个班的学生成绩
输出:
显示一个班的学生成绩
功能:
根据输入的学生成绩,计算并显示学生名次。
算法如下:
一个学生名次等于成绩高于该学生的人数+1.
2.模块名:
input
输入:
以学号为序型键盘输入一个班的学生成绩。
各个成绩之间用逗号隔开,最后以回车符号结束。
输出:
把一个班的学生成绩存入grade数组。
功能:
接受一个班的学生成绩。
调用子模块decibin把键盘输入的一个十进制数转换为二进制数。
调用子模块crlf完成回车,换行功能。
3.模块名:
rankp
输入:
从grade数组取得一个班的学生成绩。
输出:
以学号为序计算出该班每个学生的名次存入rank数组。
功能:
计算一个班的学生成绩。
算法为:
一个学生的名次等于成绩高于该生的学生人数加1.
4,。
模块名;output
输入:
把rank数组取得一个班的学生名次。
输出:
把一个班的学生名次以学号为序在总端上显示出来。
功能:
先是一个班的学生名次。
调用子模块decibin把键盘输入的一个十进制数转换为二进制数。
调用子模块crlf完成回车,换行功能。
5:
模块名:
decilin
输入:
从键盘输入一个十进制数。
输出:
把该数转换成二进制数并存入BX寄存器中。
功能:
从键盘输入一个十进制数转换成二进制数并存入BX寄存器中。
6.模块名:
crlf
输出:
向终端发出回车换行符。
功能:
完成一次回车换行操作。
7.模块名:
binidec
输入:
从BX寄存器取得一个二进制数。
输出:
在终端屏幕显示一个十进制数。
功能:
把BX寄存器中的二进制数转换为十进制数,并在终端显示出来。
调用子模块DCE_DIV用来作除法运算并显示字符。
8.模块名:
dec_div
输入:
从BX寄存器中的二进制数除以相应的十的幂,并在屏幕显示一位商。
余数保存在BX寄存器中。
有了以上的层次图及模块说明,对程序的全貌有了基本了解。
在图2.18中,我们给出了除rankp以外的其余各个子程序的程序框图。
Rankp的框图与图2.4相同。
图2.19是程序清单,图2.20是本例的运行情况。
;PROGRAMTITLEGOESHERE——Rank
;**************************************************************************
datareasegment
gradedw50dup(?
)
rankdw50dup(?
)
countdw?
mess1db'Grade?
$'
mess2db13,10,'InputError!
',13,10,'$'
mess3db'Rank:
$'
datareaends
;**************************************************************************
prognamsegment
;--------------------------------------------------------------------------
mainprocfar
assumecs:
prognam,ds:
datarea
start:
;setupstackforreturn
pushds
subax,ax
pushax
;setDSregistertocurrentdatasegment
movax,datarea
movds,ax
;MAINPARTOFPROGRAMGOESHERE
callinput
callrankp
calloutput
ret
mainendp
;--------------------------------------------------------------------------
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
;--------------------------------------------------------------------------
rankpprocnear
movdi,count
movbx,0
loop1:
movax,grade[bx]
movwordptrrank[bx],0
movcx,count
leasi,grade
next:
cmpax,[si]
jgno_count
incwordptrrank[bx]
no_count:
addsi,2
loopnext
addbx,2
decdi
jneloop1
ret
rankpendp
;--------------------------------------------------------------------------
outputprocnear
leadx,mess3
movah,09
int21h
;
movsi,0
movdi,count
next1:
movbx,rank[si]
callbinidec
movdl,','
movah,02
int21h
addsi,2
decdi
jnznext1
callcrlf
ret
outputendp
;--------------------------------------------------------------------------
decibinprocnear
;proceduretoconverdecimalonkeybdtobinary.
;resultisleftinBXregister.
movbx,0
;getdigitfromkeyboard,converttobinary
newchar:
movah,1
int21h
movdl,al
subal,30h
jlexit1
cmpal,9d
jgexit1
cbw
;(digitisnowinAX)
;multiplynumberinBXby10decimal.
xchgax,bx
movcx,10d
mulcx
xchgax,bx
;adddigitinAXtonumberinBX
addbx,ax
jmpnewchar
exit1:
ret
decibinendp
;--------------------------------------------------------------------------
binidecprocnear
;proceduretoconvertbinarynumberinBXtodecimal
;onconsolescreen
pushbx
pushcx
pushsi
pushdi
movcx,100d
calldec_div
movcx,10d
calldec_div
movcx,1d
calldec_div
popdi
popsi
popcx
popbx
ret
binidecendp
;--------------------------------------------------------------------------
dec_divprocnear
;sub_subroutinetodividenumberinBXybnumberinCX
;printquotientonscreen
movax,bx
movdx,0
divcx
movbx,dx
movdl,al
;printthecontentsofDLonscreen
adddl,30h
movah,02h
int21h
ret
dec_divendp
;--------------------------------------------------------------------------
crlfprocnear
;printcarriagereturnandlinefeed
movdl,0ah
movah,02h
int21h
;
movdl,0dh
movah,02h
int21h
;
ret
crlfendp
;--------------------------------------------------------------------------
prognamends
;**************************************************************************
endstart
程序框图如下:
实验截图如下:
实验总结:
在复杂的程序设计中,采用模块化结构可以划分功能、分界程序,使得程序有复杂变简单,变清晰。
主程序和子程序之间嵌套使用,使得写代码时思路更清楚明白,读代码时方便快捷清晰明了。
这点跟高级编程语言类似。
而此程序中变量p可以跟踪并控制输入的人数、输名字要预留缓存区、十进制码要和二进制码间相互转换,这些又体现了编程低级语言的特点。
学习汇编语言,重要的事掌握如何通过汇编指令和程序来控制计算机各个组成部件工作,完成一系列任务。
因此,学习汇编用语言与学习高级语言的不同之处是要学习如何深入到计算机的内部进行控制。
通过这次实验,加深了我对汇编语言的理解。
每一步的输入、存储、转换、输出,都需要一条条的汇编指令执行。
而且每一步都有自己的源和目标的地址,每个数据都有自己的存储空间和地址,我们可以很清晰的“跟踪”每一个数据的变化和地址的转移。
实验体会:
在复杂的程序设计中,采用模块化结构可以划分功能、分界程序,使得程序有复杂变简单,变清晰。
主程序和子程序之间嵌套使用,使得写代码时思路更清楚明白,读代码时方便快捷清晰明了。
这点跟高级编程语言类似。
而此程序中变量p可以跟踪并控制输入的人数、输名字要预留缓存区、十进制码要和二进制码间相互转换,这些又体现了编程低级语言的特点。
学习汇编语言,重要的事掌握如何通过汇编指令和程序来控制计算机各个组成部件工作,完成一系列任务。
因此,学习汇编用语言与学习高级语言的不同之处是要学习如何深入到计算机的内部进行控制。
通过这次实验,加深了我对汇编语言的理解。
每一步的输入、存储、转换、输出,都需要一条条的汇编指令执行。
而且每一步都有自己的源和目标的地址,每个数据都有自己的存储空间和地址,我们可以很清晰的“跟踪”每一个数据的变化和地址的转移。
2.7计算工资scremp
编写一个程序,接受用户输入的工作时间及工资率,显示计算得到的工资数。
本程序有三个部分组成,输入工作时间和工资率,计算工资;显示工资值。
在输入输出部分,与例2.6一样,必须考虑自负与数字的装换,以及十进制换二进制,二进制换十进制的问题。
除此之外,还应注意到本例中的输入数可能是小数。
在这里并不需要使用浮点数格式来进行计算,只是在计算中必须处理小数。
我们采用在接受输入数字是记录小数点后的位数,并把两个输入数的小数点后位数之和存放在nodec单元当中。
在计算工资的乘法中,并不考虑小数点后的存在,而输出的工资数又只取出小数点后的两位数,因此我们用SHIFT单元记录移位因子,用ADJUST单元记录舍入值。
对于不同的NODEC可以分以下情况进行处理。
1.NODEC>6
我们知道,对于16位整数而言,及其允许的最大数是65535,对于NODEC>6的数,移位因子将>=10000,该数已经超过机器允许的范围,因此本例限制NODEC的值必须<=6.如果NODEC>6,则作为溢出处理,此时将输出值变为0。
2.NODEC=3~6
此时移位因子SHIFT=(10)^nodec—2
舍入值ADJUST=1/2SHIFT
例如:
输入工作时间为8.52,工资率为10.25,则乘机为
Product=852X1025=873300
移位因子为shift=(10)^nodec—2
舍入值ADJUST=1/2SHIFT=50
作舍入及移位处理
(Product+adjust)/shift=(873300+50)/100
=8733
又如:
输入工作时间为65.245,工资率为8.52
则,product=65245X852=55588740
SHIFT=(10)^5-2=1000
Adjust=500
作舍入及移位处理
55588740+500/1000=55589240/1000
=55589
金处理的值只是取得了答案的有效值,并未考录小数点的位置,这个问题将会在输出时得到解决。
3.NODEC=0~2
在这种情况下,乘积的结果不必做舍入及移位处理,只需记录NODEC的值,并在输出显示是解决小数点的问题即可
在计算时还需啊哟说明一个问题:
由于采用整数运算,要求输入数不超过6535,任意输入数超过改制就做溢出处理,在这里我们用输出0来表示。
此外,两个输入数的成绩可能得到三十二位二进制数的结果,这用一般的运算乘法指令就可以得到。
对于这样的双精度数作除法运算时,尽管我们已经限制shift的值不超过65535,但字运算的出发指令要求双精度被除数和单精度的除数相除,其结果应该是双精度的商,否则作为溢出处理。
为了避免这种溢出情况的发生,我们采用以下程序段来作为除法。
设在以下程序段运行前,我们已取得双精度被除数在DX:
AX中,除数在shift单元中,除法运算结果的商在DX,AX中。
模块名:
begin为中控制模块
输入:
接受从键盘输入的工作时间hour和工资rate
输出:
在屏幕上显示工资值wage
功能:
根据工作时间和工资率计算工资
Wage=hour*rate
调用:
2:
模块名:
Q10SCR
功能:
清除屏幕
3:
模块名:
Q20CURS
功能:
置于光标位置
4模块名:
B10inpt
输入:
接受从键盘输入的以小时为单位的工作时间及工资率
输出:
把工作时间缓存HASPAR缓存区,吧工资率存入ratepar缓冲区
功能:
接受从键盘输入的工作时间及工资率,分别存入相应的缓存区中。
5模块名:
D10HOUR
输入:
从HRSPAR中取出工作时间
输出:
把转换为二进制的时间存入BINHRS单元中。
功能:
调用子过程M10ASBI,把工作时间从ASCLL吗转换为二进制数。
6模块名:
E10RATE
输入:
从RATEPAR中取出工资率。
输出:
把转换为二进制的工资率存入BINRATE单元中。
功能:
调用子过程M10ASBI,把工资率从ASCLL码转换为二进制数。
7:
模块名:
M10ASBI
输入:
根据调用过程给出的指针以及字符个数取得一个ASCLL字符窜、
输出:
将ASCLL字符窜转换为二进制数,结果存放与BINAL单元中
功能:
把ASCLL字符窜转换为二进制数。
同时记录输入的小数点后的位数累计在NODEC单元中。
8:
模块名:
F10MULT
输入:
从binHRAS中取得工作时间,从BINRATE中取得工资率。
输出:
根据工作时间及工资率的取值将其结果存放在DX,AX中
功能:
把工作时间和工资率的成绩经过舍入和移位处理后得到的二进制工资值存放在DX.:
AX中。
9模块名:
G10WAGE
输入:
DX,AX中的二进制工资数以及NODEC单元中的小数点后的位数
输出:
把二进制的工资数转换为ASCLL码存放在ASCWAGE为首地址的字符窜当中
功能:
10模块名
输入:
ASCWAGE中的字符窜
输出:
把字符窜在屏幕上显示出来
功能:
显示工资数
;PROGRAMTITLEGOESHERE--SCREMP
;Enterhours&rate,displaywage
;*************************************
stacksgsegmentparastack'stack'
dw32dup(?
)
stacksgends
;*************************************
datasgsegmentpara'data'
hrsparlabelbyte;Hoursparameterlist;
maxhlendb6
acthlendb?
hrsflddb6dup(?
)
rateparlabelbyte;rateparameterlist;
maxrlendb6
actrlendb?
rateflddb6dup(?
)
messg1db'Hoursworked?
','$'
messg2db'Rateofpay?
','$'
messg3db'Wage='
ascwagedb14dup(30h),13,10,'$'
messg4db13,10,'Overflow!
',13,10,'$'
adjustdw?
binvaldw0
binhrsdw0
binratedw0
coldb0
decinddb0
mult10dw01
nodecdw0
rowdb3
shiftdw?
tenwddw10
tempdxdw?
tempaxdw?
datasgends
;*************************************
codesgsegmentpara'code'
;-------------------------------------
beginprocfar;mainpartofprogram
assumecs:
codesg,ds:
datasg,ss:
stacksg,es:
datasg
;setupstackforreturn
pushds
subax,ax
pushax
;setDSregistertocurrentdatasegment
movax,datasg
movds,ax
moves,ax
;mainpartofprogramgoeshere
movax,0600h
;CALLDISP
callq10scr
callq20curs
a20loop:
callb10inpt
cmpacthlen,0
jea30
calld10hour
calle10rate
callf10mult
callg10wage
callk10disp
jmpa20loop
a30:
;calltimedate
movax,0600h
callq10scr
ret
beginendp
;-------------------------------------------
;Inputhours&rate
;
b10inptprocnear
leadx,messg1
movah,09h
int21h
leadx,hrspar
movah,0ah
int21h
cmpacthlen,0
jneb20
ret
b20:
movcol,25
callq20curs
leadx,messg2
movah,09h
int21h
leadx,ratepar
movah,0ah
int21h
ret
b10inptendp
;--------------------------------------------
;Processhours:
;--------------
d10hourprocnear
movnodec,0
movcl,acthlen
subch,ch
leasi,hrsfld-1
addsi,cx
callm10asbi
movax,binval
movbinhrs,ax
ret
d10hourendp
;---------------------------------------------
;Processrate:
;-------------
e10rateprocnear
movcl,actrlen
subch,ch
leasi,ratefld-1
addsi,cx
callm10asbi
movax,binval
movbinrate,ax
ret
e10rateendp
;----------------------------------------------
;Multiply,round,&shift
;---------------------
f10multprocnear
movcx,07
leadi,ascwage
movax,3030h
cld
repstosw
movshift,10
movadjust,0
movcx,nodec
cmpcl,06