汇编语言 第二版 王爽 实验九的三种方法
第一种我自己的方法,比较笨和繁琐
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通过改变偏移地址来实现