操控显存输出字符串
-
使用不中断的方式打印字符串
-
在8086的内存地址结构中,
B8000H~BFFFFH
这部分的内存区域为显存区域,一旦向这个地址空间写入数据,cpu会从0号偏移地址开始读取数据然后显示输出, (每写入一次数据就从0开始读取一次) -
在这块区域中,每个字符固定占用两个字节的空间,也就是
ds:[0]
和ds:[1]
存放一个字符的信息,前者存放字符具体的内容,后者存放字符对应的颜色 -
字符颜色的设置规则:
0 0 0 0 0 0 0 0 ;用8个二进制位表示字符属性
- 从高位往低位数,第1个二进制位表示是否显示闪烁痕迹,设为1即保留字符闪烁痕迹
- 第234位表示字符背景颜色,分别代表R(red)G(green)B(blue)
- 第5个二进制位表示字符是否高亮。设为1即字符高亮显示
- 第678个二进制位表示字符本身的颜色,分别表示RGB
-
data segment str db "hello world" endstr db '' data ends code segment start: mov ax, data mov ds, ax mov ax, 0B800H mov es, ax mov cx, offset endstr - str ;字符串的长度 mov bx, 0 mov si, 0 print: mov al, ds:[si] ;【】内使用bx或di或si mov es:[bx], al ;ax是16位的,为避免颜色改变,使用al add bx, 2 inc si ;si = si+1 loop print code ends end start
-
由于CPU会从0号偏移地址开始读取数据,然后显示输出,因此假如直接在6号偏移地址写入字符数据,那么前三个数据会以占位形式存在
start:
mov ax, 0B800H
mov ds, ax
mov dl, 'a'
mov ds:[0], dl
mov dl, 000000111B
mov ds:[6], dl ;输出结果为" a"
end start
- 借助字符不断刷新显示的特性,可以让字符动画显示
;让字符从左往右移动
code segment
start:
mov ax, 0B800H
mov es, ax
mov cx,100 ;移动100次
mov bx, 2
print:
mov al, ' '
mov es:[bx-2], al
mov al,'a'
mov es:[bx], al
add bx,2
loop print
code ends
end start
- 屏幕默认显示80x25个字符,全屏显示106x38个字符,那么可以根据这个特性,让字符上下移动
;从上往下移动
code segment
start:
mov ax, 0B800H
mov es, ax
mov bx, 0
mov cx, 25
print:
mov al, 'a'
mov es:[bx], al
mov dl, ' '
mov es:[bx-160], dl ;把前面的a都清除
add bx,160 ;80个字符,每个字符占用2个字符空间,
loop print
code ends
end start
;从下往上移动
code segment
start:
mov ax, 0B800H
mov es, ax
mov bx, 160*25
mov cx, 25
print:
mov al, 'a'
mov es:[bx], al
mov dl, ' '
mov es:[bx+160], dl
sub bx,160 ;80个字符,每个字符占用2个字符空间,
loop print
code ends
end start
使用键盘输入操纵字符移动
- 使用16号中断码
;使用键盘上的wsad控制字符上下左右移动
code segment
start:
mov ax, 0B800H
mov es, ax
mov bx, 0
scan:
mov ah, 00H
int 16H ;使用16号中断码
cmp al, 61H ;cmp的作用是判断al中数据的值与61H是否相等
jne scan2 ;jne意即jump not equal, 如果二者不相等,则跳转到手残2,否则往下执行
call left
jmp scan ;jmp 跳转到指令所在位置
scan2:
cmp al, 64H
jne scan3
call right
jmp scan
scan3:
cmp al, 77H
jne scan4
call top
jmp scan
scan4:
cmp al, 73H
jne scan
call down
jmp scan
right:
mov es:[bx], ' '
mov dl, 'a'
mov es:[bx+2], dl
add bx, 2
ret ;ret的作用是回到call的下一条指令
left:
mov es:[bx], ' '
mov dl, 'a'
mov es:[bx-2], dl
sub bx, 2
ret
top:
mov es:[bx], ' '
mov dl, 'a'
mov es:[bx-160], dl
sub bx, 160
ret
down:
mov es:[bx], ' '
mov dl, 'a'
mov es:[bx+160], dl
add bx, 160
ret
code ends
end start