前言:这是王爽版汇编语言第四版第187页的一道题目,因为我觉得有点难,非常有借鉴意义,所以我打算写一篇博客,顺便把题目再写一遍,这样也许会看的更仔细。我会在题目的中间加上自己的思考和分析,因为对于初学者,里面的内容确实有点多,我不加分析的话,一时半会儿自己也看不明白,具体写代码的时候,我也得看着自己的分析才能写(带颜色的部分就是我的思考)。这篇文章更适合刚入门8086汇编的小白,就是个人对复杂问题的思考。

测试环境:visual studio code的masm编译器插件和dosbox环境插件。

以下是原题:

这个编程任务必须在进行下面的课程之前独立完成,因为后面的课程中,需要通过这个实验而获得的编程经验。

编程:在屏幕中间分别显示绿色、绿底红色、白底红色的字符串‘welcome to masm!’。

我们先来分析以下题目的要求:

        1、要在dos环境下在终端上显示一个字符串‘welcome to masm!’;

        2、必须要在屏幕中间显示,而不是随便找一个地方(一开始测试的时候可以随便一点);

        3、显示一句字符串还不够,题目的意思是要显示三句字符串,颜色有区别的。

编程所需的只是通过阅读、分析下面的材料获得。

80x25彩色字符模式显示缓冲区(以下简称为显示缓冲区)的结构

内存地址空间中,B8000H~BFFFFH共32KB的空间,为80x25彩色字符模式的显示缓冲区。向这个地址空间写入数据,写入的内容将立即出现在显示器上。

含义:B8000H~BFFFFH这一段地址与显示有关,往里面写入内容就会相应地显示在屏幕上(具体用法还得参考后面地介绍)

在80x25彩色字符模式下,显示器可以显示25行,每行80个字符,每个字符可以有256种属性(背景色、前景色、闪烁、高亮等组合信息)

这样,一个字符在显示缓冲区中就要占两个字节,分别存放字符的ASCII码和属性。80x25模式下,一屏的内容在显示缓冲区中共占4000个字节。

含义:简单介绍了’80x25‘这个名字的含义,并且粗略指明了这个缓冲区的用法:

        一个字符信息要用两个字节才能表示----字符的ASCII和字符的属性。

显示缓冲区分为8页,每页4KB(≈4000B),显示器可以显示任意一页的内容。一般清空下,显示第0页的内容。也就是通常情况下,B8000H~B8F9FH中的4000个字节的内容将出现在显示器上。

含义:80x25彩色字符模式的显示缓冲区有32KB,但是我们这道题目并不需要用到这么大的空间,这32KB被分成了8份,每份是4KB,我们只要把握这4KB即可,也就是说B8000H~B8F9FH,这一段空间我们要进行编程的安排。这一段的偏移地址咱们可以先确定下来:B800H,但是我们在写的时候要写0B800H,前面有说过我们不能直接把字母放在第一个,如果第一个是字母的话,前面再放一个0.

在一页的显示缓冲区中:

偏移000~09F 对应显示器上的第1行(80个字符占160字节);

偏移0A0~13F对应显示器的第2行;

偏移140~1DF对应显示器上的第3行。

以此类推,可知,偏移F00~F9F对应显示器上的第25行。

咳咳,前面的都是开胃小菜,从这里开始我们就要进行推理和计算了。作者在这里告诉我们,前面的4000B的显示缓冲区的内容是可以被拆分的,也就是说B800:0000H代表了dos环境的左上角区域,而B800:0F0FH则代表了dos环境的右下角的区域,然后这中间的地方分别就是dos环境的中间的区域。并且一行有160个字节,一共有25行。此时我们回忆一下:我们的第二个任务就是在屏幕的中间部分显示字符串,我们需要一定的推理,把dos环境的中间部分给推理出来。

因为我们要在屏幕上写入四句”welcome to masm!“,而一页dos共有25行,25/2就是12.5,所以我们可以把这四句分别写在11,12,13行这样的地方,每一行间隔A0H,根据推算,这四段内存地址的偏移地址的行分别为((25-3)/2)*160=06E0H,0780H,0820H。

分析完行,我们再去分析具体位置,‘welcome to masm!’一共有16个字符,占16个字节,然后字符+字符属性凑成一组,所以每一句都要占16+16=32个字节--32B,而每一行都有160字节,所以我们的每一行的起始地址都是(160-32)/2=64字节。

在具体写入内存的时候,我们需要把以上两段绿色字体的内容给结合起来,作为偏移地址写进去。

在一行中,一个字符占两个字节的存储空间(一个字),低位字节存储字符的ASCII吗,高位字节存储字符的属性。一行共有80个字符,占160字节。

即在一行中:

00~01 单元对应显示器上的第1列,;

02~03 单元对应显示器上的第2列;

04~05 单元对应显示器上的第3列;

以此类推,可知,9E~9F 单元对应显示器上的第80列。

含义:作者在这里又给我们出了一个”难题“,我们需要在B800H这一段的空间中写入咱们的字符串和字符串属性,而一组这样的字符串和字符串属性占了两个字节,我们并不需要一个一个来给它移动,因为我们有占用两个字节并且可以拆分的通用寄存器AX,我们可以利用它可拆分的特点,用AH存储字符属性,用AL存储字符本身,然后把这个AX寄存器整体赋值给那一段内存空间(咱们之前已经分析好的那一段)

例:在显示器的0行0列显示黑底绿色的字符串‘ABCDEF’

(‘A’的ASCII码值为41H,02H表示黑底绿色)

显示缓冲区里的内容为:

00 01 02 03 04 05 06 07 08 09 0A 0B 0C ... 0E 0F

B800:0000  41 02 42 02 43 02 44 02 45 02 46 02 ...

...

...

B800:00A0  .. .. .. .. .. .. .. .. .. ..

可以看出,在显示缓冲区中,偶地址存放字符,奇地址存放字符的颜色属性。

说明:以上内容是原文中的一个例子,我认为这个例子很重要,看懂了这个例子,那么程序也就八九不离十地能写出来了,我们一会儿再尝试写一个样板程序(样板程序:根据提示我们可以写出一个差不多的程序但是只是完成了任务的某几个不是完成全部任务,因为学习也是需要循序渐进的,一般人不太能一来就写出一个完美的程序,需要后期修修改改)

含义:我们要输出一个字符串,但是目前我们的能力还是只能一个字符一个字符这样子去操作,而不是直接就像C++、Python那样定义一个字符串类型(对象)。我们需要把这个字符串‘welcome to masm!’拆成16个字符利用循环一个一个来操作。然后在显示缓冲区中每一个字符的显示需要有两个部分:1、字符对应的ASCII码(1B);2、字符的属性(1B)。那么也就是两个刚好挨在一起字节就能够显示一个字符了!并且还有规律:字符在前属性在后,我们可以看那个例子,也可以看作者给我们总结出来的经验。

那么我就按照我的思路先写出来一个样板程序了。

assume cs:codesg,ds:datasg
datasg segmentdb 'welcome to masm!';定义了这个字符串放在ds数据段db 16 dup (01000010b);定义了每个字符的属性
datasg endscodesg segment
start:  mov ax,datasgmov ds,axmov ax,0b800h;简单起见,我先把文字放在左上角mov es,axmov ax,0mov si,0mov bx,0mov cx,16s:mov al,[bx];把字符存放在低位mov ah,[bx+16];把属性存放在高位inc bxmov es:[si+00a0h],axadd si,2loop smov ax,4c00hint 21h
codesg ends
end start

这个样板程序里,我先把文字放在左上角,因为我们现在研究的是王爽老师给我们的那个例子,检验一下我们的分析是否是对的,在程序里我们可以看到,我们把字符和属性分别放在了低位和高位,结果成功了。

其实按照目前的情况,我们离完成王爽老师给我们布置的任务已经非常接近了,但是还是缺点什么,我在这里罗列一下,以方便后续的改进:

        1、字符串只有一个,还不是三个;

        2、字符串没有显示在dos框的正中间,而是左上角;

        3、字符串的颜色并没有符合我们任务的要求。

一个在屏幕上显示的字符,具有前景(字符色)和背景(底色)两种颜色,字符还可以以高亮度和闪烁的方式显示。前景色、背景色、闪烁、高亮等信息被记录在属性字节中。

属性字节的格式:

7       6       5       4       3       2       1       0

含义:      BL     R       G       B      I       R       G       B

闪烁       背景               高亮        前景

R:红色

G:绿色

B:蓝色

可以按位设置属性字节,从而配出各种不同的前景色和背景色。

说明:这一段其实非常好理解,我们从前面的知识可以知道,我们字符属性是用一个字节(8位)来确定的,为了能够很好地把握字体和背景的颜色,我们必须拆分了这仅有的一个字节,把分出来的8个位分别拿来用,以达到比较好的效果。

我们再对这八个位分别来分析:第一位是闪烁位,可以把它当作是Boolean类型的值,如果是1就闪烁,如果是0就不闪烁;同理,高亮也是一样的道理。当然了,作者并没有要求我们使用这二者,所以默认是0即可,如果想再尝试高难度的显示,可以使用这二者。

比如:

红底绿色:属性字节为:01000010B;

红底闪烁绿色,属性字节为:11000010B;

红底高亮绿色,属性字节为:01001010B;

黑底白色,属性字节为:00000111B;

白底蓝色,属性字节为:01110001B.

说明:这里作者给我们举了一些例子,来说明这个属性的8个位应该如何使用,属性字节末尾的那个B不是字节的意思,而是二进制的意思。二进制b,十进制d,十六进制h。

例:在显示器的0行0列显示红底高亮闪烁绿色的字符串‘ABCDEF’

(红底高亮闪烁绿色,属性字节为:11001010B-->CAH)

显示缓冲区里的内容为:

00  01  02  03  04  05  06  07  08  09  0A  0B  ...  9E  9F

B800:0000    41 CA  42 CA 43 CA 44 CA 45 CA 46 CA ....

...

...

B800:00A0

注意:闪烁的效果必须在全屏DOS的方式下才能看到。

说明:作者的提示到此就结束了,我们此时也明白了作者的意图,按照作者的提示我们可以写出程序。我们还需要根据提示把任务要求的颜色的8位二进制给写出来。

绿色:00000010B  ->  02H

绿底红色:01000010B  ->  42H

白底蓝色:01110001  ->  71H

说明:因为作者在前面给了我们一些颜色的例子,所以我们可以根据例子里的颜色提取出对应的RGB颜色,然后再拼凑出来题目中要求的颜色,过程我就不写了。(如果对颜色还有疑问请再多看看作者的例子(doge))

至此,题目的信息我们已经全部掌握了,现在我们可以开始写我们的程序了。

以下是我写的程序:

assume cs:codesg,ds:datasg
datasg segmentdb 'welcome to masm!';这是我们的目标字符串db 02h,42h,71h;这是我们的目标颜色(十六进制)
datasg ends
codesg segmentstart:mov ax,datasgmov ds,axmov ax,0b800hmov es,axmov bx,0mov si,16mov di,06e0hmov bp,64mov ax,0mov cx,3;因为我们要输出三句字符串,需要创造两层循环s1:mov ax,0mov dx,cxmov cx,16mov ah,[si]inc sis:mov al,[bx]inc bxmov es:[bp+di],axadd bp,2loop smov bx,0add di,00a0hmov bp,64mov cx,dxloop s1mov ax,4c00hint 21h
codesg ends
end start

我写的并不好,但是为了多用到前面学到的东西,所以我写了两层循环,并且可寻址的寄存器都用掉了。

终于用汇编能在屏幕上显示一点东西了,有点感动。

不得不说王爽老师写的书确实不错,既通俗移动,又循循善诱。

【王爽汇编】实验9 根据材料编程相关推荐

  1. 王爽 汇编 实验10

    1. 显示字符串 第一次写出来的代码发现只能用作特定问题,如果其他程序调用子程序将会出错.后面的题目也就无法完成.所以重新写了一遍,进入后子程序中使用的寄存器全部入栈 1 assume cs:code ...

  2. 8086汇编学习小记-王爽汇编语言实验12

    8086汇编学习小记-王爽汇编语言实验12 0号中断处理程序,开始安装在0000:0200处的程序最后用死循环导致显示不出'divided error',改成直接退出就正常显示了.注意修改ss,sp之 ...

  3. 汇编语言:汇编程序的hello world程序(实验9根据材料编程)

    实验介绍 学习每一种编程语言,第一个程序一般都是hello world,一般都是往控制台进行输出.但是学习汇编语言,汇编语言王爽这本书学习了一大半才有了往控制台输出内容.这是教材中的实验9 根据材料编 ...

  4. 【汇编语言 王爽】实验14代码

    实验需求如下: 编程,以"年/月/日 时:分:秒"的格式显示时间 注意:CMOS RAM中储存着系统的配置信息,除了保存时间信息的单元外,不要向其他单元写入内容,否则将引起一些系统 ...

  5. 实验九 根据材料编程

    南京信息工程大学实验报告 实验(实习)名称    根据材料编程    实验(实习)日期    2018年12月11日   得分        指导老师 耿学华 系 计软院 专业 计科 年级 2017级 ...

  6. 【汇编语言】(王爽)实验4解答

    题目1 编程:向内存0:200 - 0:23F 中存放数据 0 - 3FH ; 向内存 0:200 ~ 0:23f 写入数据0~3fH[字节型数据] assume cs:code code segme ...

  7. 王爽 汇编语言 实验七

    最近在看王爽老师的汇编语言,写的确实很好,简单易懂,引人入胜!相比较我们学校一些老师的书籍,那简直是··· 惨绝人寰 先说一下思路: 题目的简单表述就是:将一个段的内容复制到另一个段,不过要排列成固定 ...

  8. 汇编语言(王爽)实验十 编写子程序

    标 题: 汇编实验10-- 编写子程序 作 者: XHS_12302 时 间: 2016_7_28 16:56 实验10编写子程序 在这次实验中,我们将要编写3个子程序,通过它们来认识几个常见的问题和 ...

  9. 王爽老师汇编语言第四版:实验九 根据材料编程

    目录 1.首先是编译问题 2.显示缓存区每一行是80个字符也就是160个字节 3.当数据想要写到第二行时  这时si已经向后走了16个位移了所以不能直接+160 应该+160-32 4.视频中教程用一 ...

最新文章

  1. spring用xml还是java_Spring中如何混用XML与Java装配方式
  2. Mysql源码学习——源码目录结构
  3. 如何挖掘消费者的隐性需求?
  4. C#中深拷贝对象的简单方法
  5. 技术干货 | 视频直播关键技术和趋势
  6. 12306”的架构到底有多牛逼?
  7. SAP CRM Fiori应用Appointment startup parameters - 启动参数
  8. python处理ncdc气象数据并利用arcgis可视化
  9. 软件需求模式阅读笔记三
  10. python去除图像光照不均匀_【转载】光照不均匀图像分割技巧
  11. 【汇编优化】之X86汇编优化
  12. 推荐的C++书籍以及阅读顺序
  13. C++“”字符与字符“”相加是连接
  14. vb基础计算机应用,老师给学生的-VB计算机应用基础考试
  15. Web前端学习日记3
  16. 42招健脑秘笈——必看
  17. hp微型计算机网线怎么安装,宽带师傅教你怎么安装网线插座 看完自己都会了!...
  18. *Android 多线程下载 仿下载助手(改进版)
  19. 阿里云域名注册详解与Github绑定
  20. WCF 项目应用连载[9] - 契约中的委托 事件参数处理

热门文章

  1. Markdown 本地图片与多图床管理
  2. html是脚本吗,什么是HTML脚本(What HTML Scripts)?
  3. 测试面试常用面试套题
  4. 如何在网站上加入google地图 .net (by yfdong22)
  5. Google 的秘密- PageRank 彻底解说 中文版(二)
  6. 下单系统水平可扩展框架
  7. mysql引擎修改_如何将MySQL数据库的引擎修改为InnoDB
  8. 实例82 复数的加减乘法
  9. VQA的应用(调研)
  10. java 如何创建一个数组_如何用Java创建一个数组?