汇编语言:实验九 根据材料编程

王爽老师的汇编语言实验九主要是对循环的使用。

实验九 根据材料编程

给朋友们放上原题的描述哈:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
*注:以上图片均来源于 《汇编语言》 – 王爽 P175 - 177

Solution

在此实验之前,原书第九章对各种转移指令进行了解析。刚看到这道题时还是有点压力的,放眼望去整整两篇描述,比起一般的算法题,这个篇幅确实有点吓人了,别慌,逐步分析之后本题难度也不是很高(指完成本题,笔者学识浅薄,可能没能领悟编者的深意)。

首先书中介绍了 80 x 25 彩色字符模式的显示缓冲区。
在这里插入图片描述
一块缓冲区大致就是这么个模样(这样的显示区分为8页,每页4KB,显示器可以显示任意一页的内容,一般情况下,显示第0页的内容,如图),每一行能显示八十个字符,每个字符需要占用两个字节,分别存放字符的ASCll 码和属性,因此每一行占用160个字节,显示区共25行,因此可以将这个缓冲区抽象成一个二维数组,二维数组中,根据每个元素的行列信息,可以计算从首元素到该元素一共占用的内存空间(字节数)。

题目的要求是在第据此,若想大致的将字符显示在显存中间,需要稍微进行计算:

  • 行:一共25行,25 / 2 = 12行(向下取整)
  • 列:要显示的字符串 ‘welcome to masm!’ 一共16字节,每一行可以显示160字节,所以第一个元素 w 的位置: 第(160 - 16) / 2 = 72字节。
    可以计算得到首个字符在显示区中的偏移:
    12 * 160 + 72 = 1992 = 07C8H 字节处。
显示一行字符串! welcome to masm!

将待打印的字符串放到数据段,为后续拷贝到显存处做准备:

data segment
	db 'welcome to masm!'
data ends

ds段寄存器记录待拷贝的字符串,es段寄存器存入显存首地址B800H,在汇编中表示地址不可以以字母起始,所以需要添上一个0 -> 0B800H。

start:	mov ax, data
		mov ds, ax	;ds字符串区
		mov ax, 0B800H	;显存地址
		mov es, ax	;显存段基址

因为连续空间的字符串拷贝,都是相同的工作,因此使用循环是一个明智的选择,值得思考的是:完成拷贝循环多少次?
因为每个字符占用两个字节,低位是ASCll 码,高位存放属性,刚好是一个16位寄存器可以装下的,所以这里的安排是:寄存器bx低位bl存放字符,高位bh存放属性。

		mov cx, 16	;循环拷贝16次
		mov di, 12 * 160 + 72	;找到中间位置
		mov si, 0	;字符串区偏移

完整代码

assume cs:code, ds:data
data segment
	db 'welcome to masm!'
data ends

code segment
start:	mov ax, data
		mov ds, ax	;ds字符串区
		mov ax, 0B800H	;显存地址
		mov es, ax	;显存段基址
		
		mov cx, 16	;循环拷贝16次
		mov di, 12 * 160 + 72	;找到中间位置
		mov si, 0	;字符串区偏移
	
	s0:	mov al, ds:[si]
		mov ah, 01110001B	;设置字体属性: 白底蓝字
		mov es:[di], ax	;写入到显存
		inc si	;字符串向后偏移1
		add di, 2	;显存写入位置向后偏移两个字节
		loop s0
		
		mov ax, 4c00h
		int 21h
code ends
end start

运行展示:
在这里插入图片描述
有了一次输出的经验,对于输出三种不同样式的字符串那还不是小菜一碟?(手动滑稽)
直接上来就是无脑循环接循环… …

assume cs:code, ds:data
data segment
	db 'welcome to masm!'
data ends

code segment
start:	mov ax, data
		mov ds, ax	
		mov ax, 0b800h
		mov es, ax	
		
		mov cx, 16	;16个字母,拷贝十六次
		mov si, 0	;显存偏移
		mov di, 12 * 160 + 80;显存首字符放置处
		
	s:	mov al, ds:[si]
		mov ah, 01110001B	;白底蓝字
		mov es:[di], ax
		inc si
		add di, 2
		loop s
		
		mov cx, 16
		mov si, 0
		mov di, 13 * 160 + 80
	
	s0:	mov al, ds:[si]
		mov ah, 11000010B
		mov es:[di], ax
		inc si
		add di, 2
		loop s0
		
		mov cx, 16
		mov si, 0
		mov di, 14 * 160 + 80
		
	s1:	mov al, ds:[si]
		mov ah, 00000111B
		mov es:[di], ax
		inc si
		add di, 2
		loop s1
		
		mov ax, 4c00h
		int 21h
code ends
end start

运行效果

请添加图片描述
本次实验并没有用到最近学到的知识,更待后续钻研。

  • 5
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nepu_bin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值