汇编实验五DOS功能调用.docx

上传人:b****2 文档编号:17102736 上传时间:2023-07-22 格式:DOCX 页数:20 大小:203.12KB
下载 相关 举报
汇编实验五DOS功能调用.docx_第1页
第1页 / 共20页
汇编实验五DOS功能调用.docx_第2页
第2页 / 共20页
汇编实验五DOS功能调用.docx_第3页
第3页 / 共20页
汇编实验五DOS功能调用.docx_第4页
第4页 / 共20页
汇编实验五DOS功能调用.docx_第5页
第5页 / 共20页
汇编实验五DOS功能调用.docx_第6页
第6页 / 共20页
汇编实验五DOS功能调用.docx_第7页
第7页 / 共20页
汇编实验五DOS功能调用.docx_第8页
第8页 / 共20页
汇编实验五DOS功能调用.docx_第9页
第9页 / 共20页
汇编实验五DOS功能调用.docx_第10页
第10页 / 共20页
汇编实验五DOS功能调用.docx_第11页
第11页 / 共20页
汇编实验五DOS功能调用.docx_第12页
第12页 / 共20页
汇编实验五DOS功能调用.docx_第13页
第13页 / 共20页
汇编实验五DOS功能调用.docx_第14页
第14页 / 共20页
汇编实验五DOS功能调用.docx_第15页
第15页 / 共20页
汇编实验五DOS功能调用.docx_第16页
第16页 / 共20页
汇编实验五DOS功能调用.docx_第17页
第17页 / 共20页
汇编实验五DOS功能调用.docx_第18页
第18页 / 共20页
汇编实验五DOS功能调用.docx_第19页
第19页 / 共20页
汇编实验五DOS功能调用.docx_第20页
第20页 / 共20页
亲,该文档总共20页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

汇编实验五DOS功能调用.docx

《汇编实验五DOS功能调用.docx》由会员分享,可在线阅读,更多相关《汇编实验五DOS功能调用.docx(20页珍藏版)》请在冰点文库上搜索。

汇编实验五DOS功能调用.docx

汇编实验五DOS功能调用

福建农林大学东方学院信息工程类实验报告

系:

计算机系专业:

电子信息工程年级:

10

姓名:

廖少兵学号:

实验课程:

汇编语言

实验室号:

_______实验设备号:

实验时间:

指导教师签字:

成绩:

实验五DOS功能调用

1.实验目的和要求

1.学会DOS中关于显示功能调用指令的用法。

2.领会修改显存方法显示字符。

2.实验用的软硬件环境

实验的硬件环境是:

IBM—PC机及其兼容机

实验的软件环境是:

操作系统:

DOS2.0以上;调试程序:

DEBUG.COM;文本编程程序:

EDIT.EXE、WPS.EXE;宏汇编程序:

MASM.EXE(或ASM.EXE);连接装配程序:

LINK.EXE;交叉引用程序:

CREF.EXE(可有可无)。

3.实验内容及实验数据记录

1、输入一个字符,显示出来

2、输入一个字符串,显示出来

3、buf开始的3个的16位二进制数用十六进制数的形式显示出来

(1)理解程序

(2)输入程序,汇编,运行(在DOS状态下输入:

文件名.EXE),观察结果。

(3)如果要分行显示,程序要如何修改?

DATASEGMENT

BUFDW4F59H,56A8H,0FF90H

DATAENDS

CODESEGMENT

ASSUMECS:

CODE,DS:

DATA

START:

MOVAX,DATA

MOVDS,AX

MOVSI,0

P:

MOVBX,BUF[SI]

MOVCH,4

L:

MOVCL,4

ROLBX,CL

MOVDL,BL

ANDDL,0FH

CMPDL,10

JBNEXT

ADDDL,7

NEXT:

ADDDL,30H

MOVAH,2

INT21H

DECCH

JNZL

INCSI

INCSI

CMPSI,4

JNAP

MOVAH,4CH

INT21H

CODEENDS

ENDSTART

4、运行下列程序,在屏幕的第1行,会显示一个字符X,理解程序段

STACKSEGMENT

DB128DUP(0)

STACKENDS

CODESEGMENT

ASSUMECS:

CODE,SS:

STACK

START:

MOVAX,STACK

MOVSS,AX

MOVSP,128

MOVAX,0B800H

MOVES,AX

MOVAH,0;BIOS10H的0号功能,设置80X25的彩色字符模式

MOVAL,03H

INT10H

MOVAH,'X'

MOVES:

[160*1+40*2],AH

MOVAL,0

MOVAH,4CH

INT21H

CODEENDS

ENDSTART

5、显示

*********

*******

*****

***

*

6、编写程序,统计字缓冲区中的20个数据的正数、负数、0的个数,并将统计结果以16进制形式显示出来。

4.操作方法及实验步骤

1)直接调用DOS1号功能即可,debug环境中a命令直接编辑代码写入内存如下指令

MOVAH,01

INT21H

MOVAH,4C

INT21H

2)字符串的输入和显示,原以为在调用10号功能后需要调用9号显示功能,因此编辑代码如下

DATASEGMENT

BUFDB10

DB?

DB10DUP(?

;DB'$'

DATAENDS

CODESEGMENT

ASSUMECS:

CODE,DS:

DATA

START:

MOVAX,DATA

MOVDS,AX

MOVDX,OFFSETBUF

MOVAH,10

INT21H

;MOVDX,OFFSETBUF+2

;MOVAH,9

;INT21H

MOVAH,4CH

INT21H

CODEENDS

ENDSTART

3)

3.1&3.2我们知道要将数以16进制的形式显示就必须找到其对应的字母ABCDEF的ASCII码,ASCII码48是数字0的开始也就是16进制中的30,而3AH开始至40H为7个常用符号的ASCII码值,从41H开始才是大写字母的ASCII码值,因此将所要转化的四位二进制数与10做比较,若小于10可直接加30H得到其对应的ASCII码,若大于等于10则应多加上7跳过7个符号ASCII码得到其对应的16进制ASCII码以达到转换的目的即显示时打印其相应的ASCII码对应的字符。

3.3要达到题目要求的分行显示,从程序的跟踪可以看出在在取数时分为了两个情况,一个通过SI定位内存单元一次性取得一个16位二进制数,另一个是处理数据时循环移位取高四位数。

而要使得数据显示时换行只要在完成一个16位数据的转换后取下一个16位数时进行调用DOS2号功能输出换行符ASCII码为10即0AH便可。

所以在源代码的基础上在两次INCSI前JNZL间添加指令如下

MOVDL,0AH

MOVAH,2

INT21H

4)可以看到程序首先通过

MOVAX,0B800H

MOVES,AX

在内存开辟了附加段,段首地址为B800H并通过MOVES:

[160*1+40*2],AH以便于向B80F0H(位于B8000H~BFFFFH彩色字符模式显示缓冲区)执行MOVAH,'X'

写入字符‘X’,以达到直接改变显存内容显示。

5)

5.1分析图案

第1行打印了9列*********

第2行打印了7列*******

第3行打印了5列*****

第4行打印了3列***

第5行打印了1列*

因此有两种思路,一是通过调用DOS2号功能配合循环逐一打印字符'*',二是借鉴4)中的方法直接改变内存内容显示'*'。

但两种方法都用到了双重循环,

外层循环控制行的打印,内层循环控制列的打印。

结合图案分析和循环数与行序号不然找到如下关系:

a、1<=列数<=2*当前行序号-1

而行控制参是外层循环CX的变动,所以有

b、6-CX=当前行序号。

5.2这里选择第二种以熟悉并掌握4)中的方法

首先按a和b式,就有了偏移地址的计算式:

160*(6-CX)+2*Y。

其中1<=Y<=2*CX-1,可通过内层循环实现。

 

5.4因此有最初代码(错误)

STACKSEGMENT

DB128DUP(0)

STACKENDS

CSEGSEGMENT

ASSUMECS:

CSEG,SS:

STACK

START:

MOVAX,STACK

MOVSS,AX

MOVSP,128

MOVAX,0B800H

MOVES,AX;段装入

MOVCL,5;循环控制次数为5

MOVCH,0;高位清零

MOVDH,'*';初始打印字符

MOVAX,0

H:

;MOVBL,1;从1列开始显示

MOVDL,6;行控制参数

SUBDL,CL;控制当前行

MOVAL,160

MULDL

MOVDI,AX;保存行参数

MOVAL,2

MULCL

DECAL

(L:

)MOVAL,2

MULBL;控制当前列

ADDAX,DI;显存空间定位

MOVES:

[AX],DH;通过显存显示

INCBL;列打印自加

;INCBX

(L:

)MOVAL,2

MULCL

DECAL

;DECAX

;MOVSI,AX

CMPBL,AL;检验打印上限

;CMPBX,SI

JNAL;未打印完当前行返回继续打印

MOVDL,0AH

MOVAH,2

INT21H;打印完一行则换行

LOOPH;行打印循环

MOVAH,4CH

INT21H;退出到DOS界面

CSEGENDS

ENDSTART

6)

6.1分析题目要求有三,首先定义缓冲区存放20个有符号数据,其次对于正负数和零的统计可通过两次筛选来完成,最后是16进制的转换这在3)中已得以解决,因此有部分流程如下

这样在16进制转换时就有了一个取数的麻烦,为此考虑如果多开辟一个缓冲区BUF2来存放三个结果,下一个指针DI,一来解决了这个问题,二来筛选时通过指针的跳动也同时使得统计结果的代码得以简化,所以就有了如下流程:

6.2按分析结合流程编辑代码如下

DATASEGMENT

BUF1DB1,-3,5,26,0,6,0,24,-17,-10,

-21,-5,33,48,0,32,0,10,44,-1

BUF2DB3DUP(0)

DATAENDS

CODESEGMENT

ASSUMECS:

CODE,DS:

DATA

START:

MOVAX,DATA

MOVDS,AX

MOVCX,20

MOVAL,0

;MOVSI,OFFSETBUF1

(1);MOVDI,OFFSETBUF2

S:

CMP[SI],AL

JGENEXTCMP

JMPADDD;负数的个数

NEXTCMP:

INCDI

CMP[SI],AL

JZADDD;零的个数

INCDI

ADDD:

ADDBYTEPTR[DI],1;正数的个数

INCSI

LOOPS;统计个数

MOVDI,OFFSETBUF2

P:

MOVBX,[DI];以下为16进制的转换并显示注释参考3)见附录

MOVCH,4

;L:

MOVCL,4

ROLBX,CL

;ROLBL,CL

MOVDL,BL

ANDDL,0FH

CMPDL,10

JBNEXT

ADDDL,7

NEXT:

ADDDL,30H

MOVAH,2

INT21H

DECCH

JNZL

MOVAH,0AH

;MOVAH,2

;MOVDL,0AH

INT21H

INCDI

CMPDI,OFFSETBUF2+2

JNAP

MOVAH,4CH

INT21H

CODEENDS

ENDSTART

5.实验数据处理和分析

2)按最初想法汇编程序得到了下面可怕的结果

由此单步跟踪观察,d定位到输入的字符串所在查看,如图得知10号功能的调用并没出错,所以应该是9号的问题

单步到9号功能调用指令,p执行后,发现在debug确实调用,并显示了字符串

但在返回DOS界面却显示先前的一大堆乱码,所以认为是结束字符'$'的关系,于是修改字符缓冲区为如下

BUFDB10

DB?

DB10DUP(?

DB'$'

结果出现了如下情况,只要输入的字符少于9个都会缺失掉前面几个不唯一。

至于问题处在哪,琢磨了好一段时也没弄清楚,猜想是10号功能的调用是否已自动回显了字符串而立刻调用9号功能是不是产生了覆盖。

于是注释9号功能的调用。

结果单一的10号功能的调用就已会显了字符串,符合题目要求。

3)

3.1-1debug调试,单步跟踪如图程序进行取数操作:

不难理解,程序首先通过循环左移4位将数据高4位(二进制数)移出并补到数据低位,再将内存中一单元的数据(数的低8位二进制数)传送至寄存器DL如上图。

3.1-2数据处理操作

通过指令ANDDL,0FH将高四位清零保留低四位如图a可以看到DX由0094变为了0004,至此取得二进制数的最高四位。

将所要转化的四位二进制数与10做比较,若小于10即0到9可直接加30H得到其对应的ASCII码30H到39H如图b所示,相反若大于等于10则应多加上7跳过7个符号ASCII码得到其对应的16进制ASCII码41H到46H以达到转换的目的即显示时打印其相应的ASCII码对应的字符。

图a

图b

3.2输入程序,编译,连接,运行结果如下虽然达到了以16进制的形式打印要求却连续输出了三个数。

图c

4)立即的显示结果混在了debug环境其他字符中,以至于没能注意到,老怀疑是自己显卡的显存空间分配彩色字符缓冲区不在内存的B8000H~BFFFFH间,导致了随机更改ES段首地址,结果可想而知,无意清屏时直接在DOS下运行终于看到了字符‘X’。

5)

5.1间接寻址,MOVES:

[AL],DH寄存器的错误应用即相对适用的寄存器只有BX,BP,SI和DI错误提示如下

通过添加ADDAX,DI和MOVDI,AX指令,写入字符指令相应地改为了MOVES:

[DI],DH。

5.2更正了错误后并排错语法错误后运行结果仍然出现问题如下

结果并没有如预期的一样,从图案可以看出,错误肯定是在于列打印的控制上,

debug单步跟踪发现DI中保存的参数在每次打印时都更新为了前一次打印所计算的偏移地址也就是加上了列的增量,如下图所示,打印1行2列时,DI由00A2H即162变成了00A6即166。

5.3

因此在下一行打印之前必须保证DI不变动,所以这里的DI应由其他寄存器代替,便修改之为BP,编译运行也就得到了预期的图案。

6)汇编代码出错如下

修改错误,保证语法的正确性后,运行程序得到结果如下,显然dos2号功能调用出错了,统计结果也不正确,为此只能单步跟踪

在第一次循环时过程和数据处理均正常如下

图a第一个数第一次筛选

图b第一个数为大于等于0,DI下移

图c第一个数大于0,DI继续下移一位至0016,实现结果加1

继续跟踪发现,问题出在了每次处理完一个数据后DI未能刷新至原点0014图下

修改S:

标号至

(1)处,MOVDI,OFFSETBUF2

得到结果如下

不难发现,除了dos2号功能未修改错外,结果中后两位才是正确的结果,检查代码得知是16进制转换时寄存器高8位无用数据参与了转换,为此修改

P:

MOVBX,[DI]

MOVCH,4

L:

MOVCL,4

ROLBX,CL

P:

MOVBX,[DI]

MOVCH,2

L:

MOVCL,4

ROLBL,CL

问题想是可以得以解决。

重新汇编,并运行程序。

6.实验结果

1)G运行后提示符提示输入字符,结果如下回显输入的字符

2)DOS10号功能调用,输入字符串到自定义的缓冲区内,并会显字符串到屏幕,如下a为debug下,b为dos界面下。

图a

 

图b

3)

未进行换行操作

换行后显示结果如下

4)通过MOVES:

[160*1+40*2],AH向B80F0H写入字符'X',立即显示结果如下

5)

5.1修改DI变动的问题后,运行结果和预期的差不多,但由于是通过显存修改来显示,之前的内容未被清零,就出现了覆盖现象如下

对此,只要修改首列显示位置,及列显示上限即可,于是修改MOVBL,1为MOVBL,35(从35列开始打印),修改DECAX和MOVSI,AX为ADDAX,34结果是整体移动了位置,却又出现了错误的图案如下

原本一个简单的加法,因被我忽略了未修改时起始位子1,而多加了一个打印上限,被弄的晕头转向的,最终还是在debug单步运行时发现了问题所在。

修改34为33,终于得到了正确的结果如图

6)分析并修改一系列错误后,更正DOS2号功能调用输出换行符,得到预期结果如下,其中一行为负数个数,二行为0的个数,三行为正数个数。

7.质疑,建议,问题讨论和总结

此次实验是上机以来花了最长时间的一次,从分析各个程序,单步跟踪来理解程序的个步骤及作者的整体思路,加之利用所学分析并解决问题,让我更深入的看到了设计一个程序的思路的严谨的重要性,其中修改显存显示的方法让我掌握了一个简单却实用的DOS调用功能,而通过5)要求的再一次利用与实现使我对其认识更进一层,通过自己分析5)和6)的问题转换为数学逻辑表达式使得本繁杂的程序得以很大程度上得以简化,总之长时间的付出并没白费,虽然其中确实不甘心一次openoffice崩溃导致文档的从头重新编写,不过还算顺利完成了任务,也给自己一个不备份文件的教训了。

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 初中教育 > 语文

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2