微机实验报告汇总武汉大学物理学院.docx
《微机实验报告汇总武汉大学物理学院.docx》由会员分享,可在线阅读,更多相关《微机实验报告汇总武汉大学物理学院.docx(19页珍藏版)》请在冰豆网上搜索。
微机实验报告汇总武汉大学物理学院
实验报告一(循环程序的设计)
专业:
材料物理;姓名:
曾瑞;学号:
*************
1,实验内容
编程计算:
s=1+2+3+6...+n<=100的最大项数n以及对应的和s。
2,实验要求
①将最大项数与和数分别存入n和sum单元,用td调试,运行程序并检查结果;
②将结果在屏幕上以16进制数显示。
显示格式:
maxn=xxhsum=xxh。
3,实验目的
学习并掌握循环程序的设计方法。
4,源程序
;filename:
zengrui.asmdatasegment
ndb?
;开辟一个字节单元mesg1db'maxn=',30h,30h,'h','$'sumdb?
mesg2db'sum=',30h,30h,'h','$'dataends
codesegment
asumecs:
code,ds:
data;段分配
begin:
movax,data;段基址→dsmovds,ax
movbl,0;给bl和al赋初始值0moval,0
count:
incbladdal,blcmpal,100
jbecount;无符号数<=跳转
subal,bl;所得al大于100,故要减去bldecbl;bl的前一位才是最大项mov[n],bl;最大项数→n单元mov[sum],al;和数→sum单元movbx,offsetn
calln2_16;调用过程n2_16movbx,offsetsumcalln2_16
movah,9;9号功能调用,输出字符串movdx,offsetmesg1int21h
movah,02h;2号功能调用,输出两个空格movdl,00hint21hmovah,02hmovdl,00hint21h
movah,9;9号功能调用,输出字符串
movdx,offsetmesg2
int21h
movah,4ch;返回dos操作系统int21h
n2_16proc
nexti:
cmpbyteptr[bx],16;存储单元与16比较jcnext2;小于16转subbyteptr[bx],16;否则,减去16incbyteptr[bx+7];高位加一jmpnext1
next2:
movah,byteptr[bx]
cmpah,10;与10比较jcnext3;小于10转movch,7;否则,加7addah,ch
next3:
addbyteptr[bx+8],ah;生成低位数retendp
codeends
endbegin
5,实验结果及分析
实验结果显示为:
maxn=0dhsum=5bh。
经过验证,其结果是正确的。
需要说明的有以下几点:
①本程序还可以进一步简化。
比如,对于空格的输出,在本程序中两次调用了2号功能,当然,也可以直接在输出字符串时中直接输出。
例如,直接在data
segment中mesg1db'maxn=',30h,30h,'h','$'修改为mesg1db'maxn=',30h,30h,'h','00h','00h',$,就可以做到这点;②在设计源程序时,本人对结果输出稍微改变了一下。
实验要求是maxn=xxhsum=xxh,最终结果显示为:
maxn=0dhsum=5bh。
可以看出,字符串sum后面多了一个空格。
之所以这样做,是因为这样方便调用过程n2_16,其好处是简化了程序;
③由于实验要求sum<=100,因而在输出显示16进制数时,不用考虑其高位数大于10的情况。
所以,在设计程序时,为了简化,只是对低位数的情况进行了一次比较判断。
至于为什么在低位数大于等于10时,需要加7?
原因是这样的,即我们最终的结果都是用ascii码来显示的,16进制低位如'a'对应着ascii码41h,如果所得结果不加7,则ascii码为3ah,则对应的是':
',其记过是错误的;
④对于2进制向16进制的转换,其方法不是唯一的,有很多种。
本实验设计的源程序属于比较初级的一种,其思路是通过不断减16,来获取高位数。
另外一个思路是:
通过除法运算得商取余。
当然,也可以利用2进制与16进制的特殊关系,通过与运算0f0h,结果右移四位,得到高四位;通过与0fh运算,得到低四位,最后存入相应的存储单元。
其过程如下:
n2_16proc
moval,byteptr[bx]movah,al
andal,0f0h;与运算,al低四位清0movcl,4;右移四位,得高四位数shral,clcmpal,10jcnext1addal,7
next1:
addbyteptr[bx+7],al
andah,0fh;与运算,ah高四位清0,得低cmpah,10;四位数jcnext2addah,7
next2:
addbyteptr[bx+8],ahretendp
注意:
以上过程增加了对16进制高位数的判断
实验报告二(分支程序的设计)
专业:
材料物理;姓名:
曾瑞;学号:
2011301230019
1,实验内容
显示月份名direct;
2,实验要求
试编写一程序,根据用户键入的月份数在屏上显示该月份的英文缩写名;
提示:
(1)用跳跃表法实现多个分支转移。
可建立一个月份缩写表:
montab
db'jan','feb','mar','apr','may','jun'db'jul','aug','sep','oct','nov','dec'
(2)用户给定的月份数与其对应的英文缩写表格地址为:
montab+(月份数-1)*3
注意:
用户键入的月份数是ascii码,必须先转换为数字才能用以上公式计算;
3,实验目的
学习分支程序的结构,掌握具有分支结构程序的设计方法;
4,源程序
;filenamezengrui.asm
datasegment
mesg1db'pleaseinputthenumberformonth',0dh,0ah,'$'mesg2db'error!
',0dh,0ah,'$'
numdb3countdb?
;字符串的个数
storedb2dup(?
);用于存放输入的字符串montabdb'jan','feb','mar','apr','may','jun';月份表
db
'jul','aug','sep','oct','nov','dec'
monthdb3dup(?
),0dh,0ah,'$';暂时存放待显示的月份dataendscodesegment
assumecs:
code,ds:
datastart:
movax,data
movds,ax
moves,ax;使es与ds指向同一段movdx,offsetmesg1;输出提示信息movah,09hint21hmovdx,offsetnum;输入字符串movah,0ahint21h
cmp[count],0;输入字符个数与0比较jzexit;等于0跳转cmp[count],2jznextmovxormovjmpnext:
movmovxorcmpjzcmpjnzsubaddgoon:
cmpjzcmpjadecmovmulleaaddleamovcldrepdisp:
movmoval,[store]
al,30hah,0goonah,[store]al,[store+1]
ax,3030hah,0
goonah,1
lastah,ahal,10al,0lastal,12lastalbl,3
blsi,montab
si,axdi,monthcx,3
movsbdx,offsetmonthah,09h
;将ascii码转换成十进制;ah置零;将ascii码转换成十进制;ah为0跳转;若ah不为1,则跳转;将输入的ascii完全转化为;十进制数
;若输入数为0,则跳转
;若输入数大于12,则跳转;偏移值存放于al中;得到源的偏移地址;控制位寄存器df清零;无条件重复传递字符串int21h;显示出对应的月份jmpstart;返回到开始last:
movdx,offsetmesg2;提示出错'error'movah,09hint21hjmpstart
exit:
movah,4ch;无输入,则返回int21hcodeendsendstart
5,实验结果及分析
实验结果及分析主要有以下几点:
①按照以上的源程序,实验结果比较理想。
用户可以通过输入一位或者两位字符来查询月份,而且比如:
输入'9'与输入'09'的效果是一样的;对于输入的数等于0,大于12或者为其他字符,则在屏幕上显示'error',提示所输入内容是不合法。
所以,本程序是正确的,功能符合要求,已经通过了实践的检验;
②需要说明的是,在本程序中对于输出相应的月份,是通过首先在数据段中定义一个变量,用于存放待显示的月份,这是一种间接的做法。
其实,更为直接的做法为:
在建立月份表时,可以直接在每个月份缩写后加0dh,0ah,'$',即为'jan',0dh,0ah,'$'?
?
,这样用户给定的月份数与其对应的英文缩写表格地址为:
montab+(月份数-1)*6。
通过这种方法,可以不用通过字符串传递,就可实现月份的输出。
但是,在定义中比较冗长,所以本程序没有采用这种方法;
③对于将ascii码转换成十进制数,本程序采用的是通过异或,成功实现转换,当然,也可以通过将源操作数减去30h得到相应的数,其效果是一样的。
另外,在对于判断所输入数是否有效时,并没有从一开始就进行判断,而是在通过一系列操作,得到al中存放的数,比较其值与0和12的大小,对于超出其范围的,则是无效的数,立即跳转。
由于程序设计得比较严谨,不会出现输入一个无效数而显示出月份的情况;
④从开头处可以看到,我使es与ds指向同一段,是因为在前面的定义中没有出现附加段的定义,后面的字符串的传递是在同一数据段中进行的。
如果,字符串的传递不是在同一段中进行,那么es和ds的指向是不同的,而且在要显示出附加段中的字符串时还必须对ds中的数据进行压栈;实验报告三(子程序结构的设计方法)
专业:
材料物理;姓名:
曾瑞;学号:
2011301230019
1,实验内容编程计算n!
,从键盘上接受10以内的数,计算出其阶乘后在屏幕显示结果;
2,实验要求
用子程序编写计算n!
的代码以及结果显示代码;
3,实验目的
学习子程序结构,了解子程序的调用、返回的过程,掌握其编程的方法;
4,程序流程图
5,源程序
;filenamezeng.asmdatasegment
mesg1dbpleaseinputanumberbetween0and9,0dh,0ah,$mesg2dberrormessage!
0dh,0ah,$mesg3db!
=,$storedw?
dataends
stacksegment
db256dup(?
)
stackends
codesegment
assumecs:
code,ds:
data,ss:
stackmainprocfar
start:
movax,datamovds,ax
movdx,offsetmesg1;输出提示语句movah,09hint21h
movah,1int21h
cmpal,20hjzexit
xoral,30hcmpal,0jnznext
incalnext:
cmpal,9jaerrorpushaxleadx,mesg3movah,09hint21hpopax
callcalculcallprintcallcrlfjmpstart
error:
movdx,offsetmesg2movah,09hint21hjmpstartexit:
movah,4chint21hmainendp
calculproc
movah,0
movcx,axmoval,1movdx,0movbx,0again:
incbx
;键盘输入一个字符并回显;如果输入的是空格,则返回;将ascii码转换成二进制数;将al中数与0比较;若为0,则加一;与9进行比较;若大于9,则跳转
;将ax中内容堆栈,保护输入数;输出提示信息,提醒输入有误;cx存放输入的数字;将ax初始值赋1mulbx
cmpbx,cx
jnzagain;若bx小于cx,则循环执行ret
calculendp
printproc
movcx,0
cmpdx,0;将dx中内容与0比较jzthen
movbx,10divbxpushdxinccxthen:
movdx,0
mov[store],axmovbx,10divbxpushdxinccxcmpdx,[store]
jnzthendisplay:
popdxadddl,30hmovah,2int21hloopdisplayretprintendp
crlfproc
movdl,0dhmovah,2int21hmovdl,0ahmovah,2int21hretcrlfendpcodeends
endmain
;[store]是个字单元,在数据段已;有定义
;将余数堆栈
;cx当计数器,存放堆栈的次数;若余数与被除数不等,继续循环;出栈,把数据赋给dx
;dl存放欲显示数的ascii码;显示回车与换行
5,实验结果及分析
(1)程序运行结果如下:
pleaseinputanumberbetween0and90!
=1
pleaseinputanumberbetween0and91!
=1
pleaseinputanumberbetween0and92!
=2
pleaseinputanumberbetween0and93!
=6
pleaseinputanumberbetween0and94!
=24
pleaseinputanumberbetween0and95!
=120
pleaseinputanumberbetween0and96!
=720
pleaseinputanumberbetween0and97!
=5040
pleaseinputanumberbetween0and98!
=40320
pleaseinputanumberbetween0and99!
=362880
pleaseinputanumberbetween0and9herrormessage!
注意:
当输入其他字符时,比如h,则显示'errormessage!
'
(2)需要说明的有以下几点:
①用int21h指令执行功能调用会影响ax中的数据,因此在调用前必须将ax中的数据进行堆栈操作。
在本实验中遇到的问题之一即在此:
由于在之前没有将ax中的数据进行堆栈保护,运用int21h功能后,al变成了24h,结果最后所有的输出都变成了0;
②实验过程中遇见的另外一个问题是,1-8的阶乘都显示正常,只有9的阶乘有问题,显示为35200。
原因是先前的循环体部分是:
again:
mulcxloopagain
其运行方式为cx减1后参与乘法运算,这种方式对于1-8的阶乘计算没有问题,因为8!
=40320<65535,而当9*8*?
?
*3=181440>65535,此时dx存放了0002h,ax存放了c4c0h;对ax做乘法运算(乘以2)后,dx位存放0001h,ax存放8980h;对ax做乘法运算(乘以1)后,dx位为0000h,ax为8980h,因此结果为35200。
为了避免出现上述的情况,将运行方式改为1*2*3?
?
*9的方式,即递增的方式,当1*2*3?
?
*9时,dx存放0005h,ax存放8980h,因此最终结果才为362880;
③在本程序print过程中采用了循环除10的方法,获得各位整数,而且采用了堆栈--出栈的方式,实现了高位到低位数的输出。
这不仅比采用"除10000,再除1000,?
?
"的方法在程序上要简洁,而且输出结果也要简洁,比如前者6!
=720,后者的6!
=00720。
实验报告四(图形方式程序设计基础)
专业:
材料物理;姓名:
曾瑞;学号:
2011301230019
1,实验内容动态画圆球;
2,实验要求
在屏幕中央画一个逐渐膨胀的或者逐渐"收缩"的实心圆;
3,实验目的
熟悉对图形方式下的程序设计的一些基本技巧,掌握对bios功能的调用;
4,程序的流程图
5,源程序
;filenamezz.asm
writemacrox,y1,y2localll,first
movcx,x;列值→cxmoval,color;设置像素值movbh,0
movdx,y1;行值→dxjmpfirst
ll:
incdxfirst:
movah,0chint10hcmpdx,y2jnzllendm
datasegmentrdb?
r2dw?
adb?
a2dw?
hdw?
yydw240xxdw320
colorequ14rightdw?
leftdw?
updw?
downdw?
countdb?
dataendscodesegment
assumecs:
code,ds:
datastart:
movax,datamovds,ax
movr,1movcount,100
callscreenlast:
calldrawcalldelay
incrdeccountjnzlast
waitin:
movah,1;行值加一;写像点;存放半径r的平方;存放横轴坐标值a的平方;存放纵轴坐标值;原点的行值和列值;像素值,对应黄色;计数器,画圆次数;半径值初始赋1;半径加一;程序暂停,等待键入
int21h
movax,2;恢复80×25黑白文本方式
int10hmovah,4ch
int21h;返回dos
calculproc;子程序,计算?
?
=rmoval,amulal
mova2,axmoval,r
mulalsubax,a2movcx,0last1:
movdx,cx
adddx,dxincdxsubax,dx
jcexit1inccxjmplast1
exit1:
movh,cxretcalculendp
delayproc
movah,86hmovcx,0
movdx,10000int15hretdelayendp
drawprocmova,0again:
callcalculmovch,0movcl,a
addcx,xxmovright,cxmovch,0movcl,anegcxaddcx,xx
;计算a2;计算r2;ax存放r2?
a2;得到一个偶数2k;奇数2k+1;若有借位,跳转;cx中的值即为h的近似值
;延时10ms
;得到右半圆像点列值movleft,cx;得左半圆像点列值movdx,hadddx,yy
movdown,dx;得下半圆像点行值movdx,hnegdxadddx,yy
movup,dx;得上半圆像点行值writeleft,up,down;宏调用,画左半圆writeright,up,down;宏调用,画右半圆incamoval,r
cmpa,al;比较a与半径的大小jnzagainretdrawendpcodeendsendstart
6,实验结果及分析
(1)实验结果:
在运行程序中,可以看到黑色的显示屏中央出现一个黄色的
小圆,然后小圆不断变大,经过大约两分钟,圆球停止生长。
键入任意键,就可以返回到dos。
(2)结果分析如下:
①本实验程序的设计思路是通过从左到右画弦的方式,得到实心圆;然后
通过增大每次画圆的半径,加上延时,来显示不断增大的圆球的效果。
由于每次画圆的操作较多,用时比较长,所以可以明显地观察到从左到右画圆的动作。
严格地来说,用此种方式画的圆球的动态效果不是特别理想,因为其与真正的膨胀本质还是有很大的区别,真正的膨胀沿径向生长。
所以,比较理想的设计方案是通过不断画圈的方式。
但是此处又有一个问题,那就是圈与圈之间会有空隙,这将会导致得到的实心球上会有许多稀疏点,影响效果;②对于行值的计算,运用到了勾股定理,即?
?
=r。
特别是对于开根号的计算,其基本原理是1+3+5+?
?
+(2k+1)=k2;当然,也可以直接将给定值c的平方与h2进行比较,若c的平方小于h2,则c加一,继续循环,最终得到h的近似值;
③在本每次画圆都将之前画的圆覆盖,没有利用之前的已有的圆,使得程
序的执行时间较长,但由于延迟时间有一定限制,所以这样可以更明显的显示出动态过程;每次将画圆时都将前一次圆的边界保存,画弦时只需要将原弦加长,就可以实现这一想法。
实验报告五(可编程定时器/计数器(8253))
专业:
材料物理;姓名:
曾瑞;学号:
2011301230019
一、实验目的
1)学会8253芯片和微机接口原理和方法。
2)掌握8253定时器/计数器的基本工作原理、工作方式和编程原理。
二、实验内容
按图6虚线连接电路,将计数器0设置为方式0,计数器初值为n(n≤0fh),用手动逐个输入单脉冲,编程使计数值在屏幕上显示,并同时用逻辑笔观察out0电平变化(当输入n+1个脉冲后out0变高电平)。
图6
三、程序的流程图
四、源程序
;filenamezzz.asm
codesegment
assumecs:
code
start:
moval,10h;控制字:
通道0,只读低字节
movdx,0cb03h;控制口
outdx,al;写入控制字
movdx,0cb00h;计数器0
moval,0fh;预置计数值n=15