1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
首先每一行是160个字节,一共2580列。初始显存位B800:0000开始
show_str:push cx
push dx
push si

mov ax B800
mov es,ax#先把段地址放起来
mov ax,0
mov al,160
mul dh#一行160,✖️行数结果存在ax中
mov bx,ax#行偏移地址(乘法保存在哪来着)
mov al,2
mul dl
add bx,ax#行偏和列偏加起来


mov di,0
mov al,cl#字符属性
mov ch,0
show:mov cl,ds:[si]
jcxz ok#如果放进来直接就是0,那么直接就推出了。

mov es:[bx+di+0]#显示到缓冲区
mov es:[bx+di+1]
add di,2#下一个字符
inc si
jmp short show跳回去把下一个字符存到cl里面

ok:pop si
pop dx
pop cx
ret
code ends
end start

下面再来一遍:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
show_str:push cx
push dx
push si

mov ax,B800#找到显存的段地址!
mov bx,ax#先存起来
mov ax,0
mov al,160#8位乘法即可
mul dh#找到行的偏移地址,应该✖️完之后存进ax了,因为没有超过16位。
mov es,ax#也存起来,再找列偏移地址
mov al,2#8位乘法即可
mul dl
add es,ax#偏移地址加在一起
#终于把乘法和偏移地址练明白了。。

mov di,0
mov al,cl#属性存起啦
mov ch,0
show:mov cl,ds:[si]#然后判断,如果cl为0直接就出去了,所以我们要先把高位置0
jcxz ok
#如果判断失败的话
mov bx:[es+di+0], cl#进行显示
mov bx:[es+di+1], al
add di, 2#换成下一个字符
inc si#提前跳到下一个字符
jmp short show#继续循环!

ok:pop cx
pop dx
pop si

时隔几个月再复习一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
首先每一行是160个字节,一共25行80列。初始显存位B800:0000开始
assume cs:code
data segment
db 'Welcome to masm!', 0//以0结尾
data ends

code semgnet//代码段
start: mov ax, data
mov ds, ax
mov si, 0
mov dh, 8
mov dl, 3//先写好列号和行号,然后是绿色
mov cl, 2
call show_str
mov ax, 4c00h
int 21h//调用show_str之后直接退出
show_str: push cx
push dx
push si

mov ax, B800h
mov es, ax//先存起来,段地址
mov ax,0
mov al,160//每行160个
mul dh//8行第一个位置,存到了ax中。
mov bx, ax//再存起来,再找列偏移
mov al, 2
mul dl//结果存在ax中
add bx, ax加起来一共走过多少字节

mov di, 0
mov al, cl
mov ch, 0
show:mov cl,ds:[si]//把字符移动到cl,然后判断cx是否为0,为0就结束了
jcxz ok

mov es:[bx+di+0],cl
mov es:[bx+di+1],al//因为字符有两个属性,字和颜色等,占用两个字节
add di,2
inc si//下一个循环执行下一个字符了
jmp short show

ok:pop si
pop dx
pop cx
ret

code ends
end start