2020-11-06

汇编语言 第二版 王爽 实验九的三种方法
第一种我自己的方法,比较笨和繁琐

assume cs:codesg,ds:datasg,ss:stack

datasg segment
  dw 0257h,0265h,026ch,0263h,026fh,026dh,0265h,0020h,0274h,026fh,0020h,026dh,0261h,0273h,026dh,0221h
  dw 2457h,2465h,246ch,2463h,246fh,246dh,2465h,2420h,2474h,246fh,2420h,246dh,2461h,2473h,246dh,2421h
  dw 7157h,7165h,716ch,7163h,716fh,716dh,7165h,7120h,7174h,716fh,7120h,716dh,7161h,7173h,716dh,7121h
  ;之前 打算是db'welcome to masm!'和db 02h,24h,71h但是没有想到可以用奇偶数通过al把他们存放到es:[di];这样做会多一个循环,一个大循环表示三行,两个小循环分别把字符ASCII码和属性分别放到偶、奇数位
datasg ends

stack segment
  db 8 dup (0);设置一个栈,主要是为了两层循环把cx,ax放进去
stack ends

codesg segment
  start:	mov ax,datasg
			mov ds,ax
			mov ax,0b800h
			mov cx,3
			mov bx,0
			
		 s: push cx
		    push ax  ;这里要注意,先入栈的后取出,fist in last out
			mov es,ax
		    mov cx,16
			mov di,720h;12行中间位置开始,所以11*160+64化为十六进制
			
		s1: mov ax,ds:[bx]
		    mov es:[di],ax
			add bx,2
			add di,2
			loop s1
			
			pop ax
			add ax,0ah;这里说明我们想要换行有两种方法,第一用偏移地址加a0h,第二个用段地址加ah
			pop cx
			loop s
			
			mov ax,4c00h
			int 21h
codesg ends
end start
			
			

第二种网上比较普遍的做法,通过三个独立循坏实现

在这里插入代码片
assume cs:code
data segment
	db 'welcome to masm!'
data ends

code segment
  start:mov ax,data
		mov ds,ax
		mov ax,0b800h
		mov es,ax
		mov si,0
		mov di,10*160+80;每页25行,在10行,11行,12行的中间显示
		mov cx,16
		
	s1: mov al,ds:[si]
		mov ah,02h ;绿色
		mov es:[di],ax
		inc si
		inc di
		inc di
		loop s1
		
		mov si,0
		mov di,11*160+80
		mov cx,16
		
	s2: mov al,ds:[si]
		mov ah,24h ;绿底红色
		mov es:[di],ax
		inc si
		inc di
		inc di
		loop s2
		
		mov si,0
		mov di,12*160+80
		mov cx,16
		
	s3: mov al,ds:[si]
		mov ah,71h ;白底蓝色
		mov es:[di],ax
		inc si
		inc di
		inc di
		loop s3
		
		mov ax,4c00h
		int 21h
		
code ends
end start

第三种是小甲鱼老师的做法,通过嵌套循环实现,和第二种做法的主要区别就是处理属性的做法,方法二直接赋值,例如 mov ah,02h,把属性放在ax高八位,字符ASCII码放在ax低八位,而方法三主要通过循环实现,把属性放在奇数位,把字符ASCII码放在偶数位

assume cs:code,ds:data,ss:stack

data segment
	db'welcome to masm!'
	db 02h,24h,71h
data ends

stack segment
	dw 8 dup(0)
stack ends

code segment
start:	mov ax,data
		mov ds,ax
		mov ax,stack
		mov ss,ax
		mov sp,10h
		
		xor bx,bx			;bx清零,用来索引颜色
		mov ax,0b872h		;算出屏幕第12行中间的显存的起始位置放入ax中,11*160+64化为16进制720h
		
		mov cx,3			;s3循环控制行数,外循环为3次,因为要显示三个字符串
	s3: push cx				;三个进栈操作为外循环s3保存相关寄存器的值
		push ax				;以防止他们的值在内循环中被破坏
		push bx
		
		mov es,ax
		
		mov si,0			;si用来索引代码列的字符
		mov di,0			;di用来定位目标列
		
		mov cx,10h
		;s1循环控制存放的字符,内循环为10h次,因为一个字符串中含10h个字节
	s1: mov al,ds:[si];建议这边先mov ah,0;
		mov es:[di],al
		inc si
		add di,2
		loop s1				;此循环实现偶地址中存放字符
		
		mov di,1			;di的值设为1,从而为在显存奇地址中存放字符的颜色 属性做准备
		pop bx
		mov al,ds:10h[bx]	;取颜色属性
		inc bx
		
		mov cx,10h			;第二个内循环也为10h次
	s2: mov es:[di],al
		add di,2
		loop s2				;此循环实现奇地址中存放字符的颜色属性
		
		;以下四句为下一趟外循环做准备
		pop ax
		add ax,0ah			;将显存的段起始地址设为当前行的下一行
							;在段地址中加0ah,相当于在偏移地址中加了0a0h(=160d),注意段地址加的是0ah,偏移地址加的是a0h
		pop cx
		loop s3
		
		mov ax,4c00h
		int 21h
code ends
end start

难点:
1.如何把字符ASCII码和属性组合到一起
2.如何把最后要显示的字符串放在屏幕中间位置,
3.嵌套循环的时候要用到栈来临时保存一些数据,如 ax,cx
4.怎么进行换行显示,方法1和方法3都通过改变段地址(主要是在嵌套循环中,偏移地址本身就在迭加,这时候要想用到偏移地址换行,就得[bx+si]),方法2通过改变偏移地址来实现

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值