1. 掌握十进制两位数输出的方法编程
2. 理解 80×25 彩色字符模式显示原理框架
3. 综合应用寻址方式和汇编指令完成应用编程oop
1. 复习数值和数字字符之间的转换方法,div 指令用法学习
2. 学习 P187-189 支撑材料及「实验 9 提示」(本文档最后一部分)优化
3. 复习灵活的寻址方式及本次实验中用到的指令,如 mov, loop,div 等。spa
1. 补全程序 t1.asm,完成在屏幕上输出内存单元中的十进制两位数设计
(1)在程序框架中补全代码以下:code
(2)分析:第一个空显然的须要将data段地址放到ds中,经过ax寄存器两条指令blog
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)运行结果如下:
4、总结
(1)经过这次实验,练习掌握了div命令的操做以及掌握十进制两位数输出的方法。
(2)汇编语言的学习使咱们对以前所学习的高级语言有了一个更深的理解。