实验 9 根据材料编程
Posted mr-gao1
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实验 9 根据材料编程相关的知识,希望对你有一定的参考价值。
一、实验目的
1. 掌握十进制两位数输出的方法
2. 理解 80×25 彩色字符模式显示原理
3. 综合应用寻址方式和汇编指令完成应用编程
二、实验准备
1. 复习数值和数字字符之间的转换方法,div 指令用法
2. 学习 P187-189 支撑材料及「实验 9 提示」(本文档最后一部分)
3. 复习灵活的寻址方式及本次实验中用到的指令,如 mov, loop,div 等。
三、实验内容
1. 补全程序 t1.asm,完成在屏幕上输出内存单元中的十进制两位数
(1)在程序框架中补全代码如下:
(2)分析:第一个空显然的需要将data段地址放到ds中,通过ax寄存器两条指令
mov ax,data
mov ds,ax来实现即可;
第二个空,需要将被除数12,即段地址为ds,偏移地址为0的内容送到寄存器ax中,
ax是16位寄存器,所以应该应该放入低8位AL寄存器中。
接下来一个空同上,按照提示,将商12保存到注释中指定单元,即偏移地址为1的数据段
mov dl,ds:[1]
接下来一个空需要将数值转换为数字字符,根据ASCII码,数字字符与相应的数字之间相差48,
也就是30h。所以只要使用add命令加上30h就行了。
最后两个空其实也是同上的,余数在偏移地址为2的数据段(ds:[2]),最后一个空同理,加上48(30h)
数值变成数字字符。
(3)代码执行结果如下:
2. 补全程序 t2.asm,完成在屏幕上输出 data 段定义的 5 个十进制两位数,数据和数据 之间以空格间隔。
(1)补全代码如下:
(2)分析:
第一处参考t1.asm的内容可知,需要将data表示的段地址送到ds中,通过
mov ax,data
mov data,ds
来实现
因为这里肯定需要用到循环,所以cx = 5,有五个数表示循环五次,bx初值为零
显而易见是为了用[bx]方便表示偏移地址从0到5,inc bx在循环中依次递增;
下面我们就进入了loop循环阶段
我们先来探讨一下如何输出一个字符,不急着写。
题目要求的是输出五个数,每个中间隔有空格。
mov ah,2
mov dl,待输出字符或其ASCⅡ码
int 21h
根据提示这个格式是用来输出字符的,所以说我们要执行的五次循环是每次循环按顺序输出一个数再加一个空格
首先这个空格是很好输出的,经查询空格的ASCII码是32(即20h),所以在这个loop循环的末尾处先写上这个代码
mov ah,2
mov dl,20h
int 21h
inc bx
loop s
后面的inc bx,loop s显然不用解释了,inc bx每次加一,灵活表示内存地址,这样我们可以按顺序依次取一个数。
现在程序的末尾我们已经写好,空格已经可以输出,接下来只要在循环中输出五个数即可
如何做到?似乎按照提示,我们只需要找的这五个数的ASCII码就行了,但这五个数都是两位数,
显然ASCII码中的数字是设置了0到9的,对于两位数,我们无法直接找到它的ASCII码。
那么我们可以换个思维,一个数拆成两份,个位数和十位数,我们分别输出就行了。
如何将一个两位数拆成个位数和十位数分开,在C语言中我们有过很多这样的题目,只要让这个数除以10可以得到它的十位数,
再用%运算就能得到它的个位数。在汇编语言中甚至不用这么麻烦,只要用div命令,我们就可以同时的到它的商(即两位数的十位数)和余数
(即两位数的个位数),其中商放在al中,余数放在ah中,再用
mov ah,2
mov dl,待输出字符或其ASCⅡ码
int 21h
分别按顺序输出商和余数即可。
分析道这里已经很清楚了,循环的开始先要将ax置为0,把除数10放在dl中。后面的程序具体细节就不再赘述。
但仍然需要注意t1.asm中已经提过的,我们得到的余数和商都是一个数值,我们所能输出的是数字字符,按照ASCII码中两者相差48(30h)
,我们加上即可。
当然还需要解释一点,可能有人会觉得按照
mov ah,2
mov dl,待输出字符或其ASCⅡ码
int 21h
的格式才能输出字符,为什么我们的上述代码中,商的输出是用add dl,30h的
,事实上add的作用很明显是相加后再送回,所以实际上送回的那一步包含在内了。
(3)实验结果如下:
显然实验成功
3. 教材实验 9(P187)
在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串’welcome to masm!‘
代码如下:
; p187 实验9 assume ds:data, cs:code, ss:stack data segment db ‘welcome to masm!‘ db 2H,24H,71H ;字符串属性值 data ends stack segment db 2 dup(0) stack ends code segment start: mov ax,stack mov ss,ax mov sp,0 mov ax,data mov ds,ax ;字符串及属性值所在段的段地址送入ds mov ax,0b800H mov es,ax ;80×25彩色字符模式显示缓冲区段地址送入es mov si,0 ; 每次循环后,es:[bx],bx应该+2,bx无法+2,靠si辅助 mov di,0 ; di控制颜色属性 mov cx,3 ; 外层循环 s0: push cx ; cx暂存 mov bx,0 ; bx控制字符获取,每次向后获取一位 mov cx,16 ; 控制循环次数 s: mov al,ds:[bx] mov es:[bx+si], al ; 待显示字符送入显存单元b800:0 mov ah,ds:[di+16] mov es:[bx+si+1], ah ; 待显示字符颜色属性(绿色)送入显存单元b800:1 inc si inc bx loop s add si,144 ;换行 inc di pop cx ;暂存的cx取出 loop s0 ; 添加代码,通过循环逐个将每个字符及其属性送入相应的显示缓冲区对应行 ; 即:将data段的字符及属性通过循环逐个mov到显示缓冲区(es)段相应的单元内 ; 可以先尝试分别写三段代码,每次完成一行的显示 ; 程序运行起来后,再尝试通过灵活的寻址方式和循环,对三段代码修改和简化 ; 学习第10章子程序后,还可以进一步完善优化,设计子程序,将行号、列号、颜色属性设置成入口参数 mov ax,4c00h int 21h code ends end start
(2)分析:
我们要输出的是两行字符串,而每一行字符串实际上在前面的实验中也已经说过,只能逐个输出,这样以来我们就要设置内存循环和外层循环。
内存循环用来逐个输出字符,这条字符串共有16个字符,所以在这里我们需要设置cx = 16;外层循环用来控制换行,输出不同颜色的。
根据书中的知识在一行中,一个字符占两个字节的存储空间,低位字节存储字符的ASCII码,高位字节存储字符的属性。所以bx每次要加2,需要si的帮助来实现。
(3)运行结果如下:
四、总结
(1)通过此次实验,练习掌握了div命令的操作以及掌握十进制两位数输出的方法。
(2)汇编语言的学习使我们对之前所学习的高级语言有了一个更深的理解。
以上是关于实验 9 根据材料编程的主要内容,如果未能解决你的问题,请参考以下文章