阅读 76

x86汇编语言之显存操控屏幕输出

操控显存输出字符串

前面咱们介绍过使用中断的方式输出字符串, 今天我们学习一种不使用中断的方式实现字符串的打印

在8086的内存地址结构中,B8000H~BFFFFH这部分的内存区域为显存区域,一旦向这个地址空间写入数据,cpu会从0号偏移地址开始读取数据然后显示输出, (每写入一次数据就从0开始读取一次)

代码尝试:

start:    mov ax,0B800H    mov ds,ax         mov dl,'a'               mov ds:[0],dl end start 复制代码

在这块区域中,每个字符固定占用两个字节的空间,也就是ds:[0]ds:[1]存放一个字符的信息,前者存放字符具体的内容,后者存放字符对应的颜色

比如:

start:    mov ax,0B800H    mov ds,ax         mov dl,'a'               mov ds:[0],dl        mov dl,00000100B ;让字符以红色显示              mov ds:[1],dl end start 复制代码

字符颜色的设置规则:

0 0 0 0 0 0 0 0  ;用8个二进制位表示字符属性 复制代码

从高往低数,第一个二进制位表示是否显示闪烁痕迹

start:    mov ax,0B800H    mov ds,ax         mov dl,'a'               mov ds:[0],dl        mov dl,10000000B ;保留字符闪烁痕迹           mov ds:[1],dl end start 复制代码

第234个二进制位表示字符背景颜色 分别代表:RGB,即red、green、blue

start:    mov ax,0B800H    mov ds,ax         mov dl,'a'               mov ds:[0],dl        mov dl,01000000B ;背景颜色设为红色           mov ds:[1],dl end start 复制代码

第5个二进制位表示字符是否高亮

start:    mov ax,0B800H    mov ds,ax         mov dl,'a'               mov ds:[0],dl        mov dl,00001100B ;字符颜色设置为红色 并且高亮显示     mov ds:[1],dl end start 复制代码

第678个二进制位表示字符本身的颜色 分别代表:RGB,即red、green、blue

start:    mov ax,0B800H    mov ds,ax         mov dl,'a'               mov ds:[0],dl        mov dl,00000111B ;背景颜色设为白色  系统默认颜色是白色      mov ds:[1],dl end start 复制代码

由于cpu会从0号偏移地址开始读取数据然后显示输出,因此假如你直接在6号偏移地址写入字符数据, 那么前面三个数据会以占位形式存在

start:    mov ax,0B800H    mov ds,ax         mov dl,'a'               mov ds:[0],dl        mov dl,00000111B      mov ds:[6],dl ;输出结果为"   a" end start 复制代码

字符串打印

data segment str db 'hello pangshu' 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 dl,ds:[si]                       mov es:[bx],dl            mov dl,00000111B ;背景颜色设为白色  系统默认颜色是白色              mov es:[bx+1],dl              inc si            add bx,2            loop print code ends end start 复制代码

借助字符不断刷新显示的特性,可用让字符动画显示

;让字符从左往右移动 code segment     start:                                    mov ax,0B800H            mov es,ax                mov bx,0         mov cx,30     print:                 mov es:[bx],' '             mov dl,'a'                    mov es:[bx+2],dl                    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 es:[bx],'a'             mov dl,' '                    mov es:[bx-160],dl                    add bx,160   ;为什么是160而不是80 以内一个字符占两个字节的空间, 80个字符总共偏移了160            loop print code ends end start ;让字符从下往上移动 code segment     start:                                    mov ax,0B800H            mov es,ax                mov bx,160*24         mov cx,25     print:                 mov es:[bx],'a'             mov dl,' '                    mov es:[bx+160],dl                    sub bx,160   ;为什么是160而不是80 以内一个字符占两个字节的空间, 80个字符总共偏移了160            loop print code ends end start 复制代码

另外, 让字符斜着移动

;让让字符斜着移动 code segment     start:                                    mov ax,0B800H            mov es,ax                mov bx,0         mov cx,25     print:                 mov es:[bx],'a'             mov dl,' '                    mov es:[bx-161],dl                    add bx,161   ;向右斜加偏移量 向左斜减偏移量            loop print code ends end start 复制代码

补充: 在8086中系统提供了一个显示服务(Video Service)中断供我们使用,使用10H这个中断码也可以打印带有颜色属性的字符串

;示例1: mov ah,2 ;放置光标 mov bh,0 ;第0页 mov dh,5 ;行号 mod dl,12 ;列号 int 10H ;示例2: mov ah,9 ;在光标的位置显示字符 mov al,'a' ;字符 mov bl,11001010B ;颜色 mov bh,0 ;第0页 mov cx,3 ;重复显示3次 int 10H 复制代码

使用键盘输入控制字符移动

使用16号中断码

;使用键盘控制字符移动 code segment     start:                                    mov ax,0B800H            mov es,ax    mov bx,0         mov cx,30                    scan:           mov ah, 00H        int 16H               cmp al,61H ;判断两个值是否相等        jne scan2  ;jmp not equal 如果两者不相等 则跳转到scan2 否则往下执行        call  left         jmp scan             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                      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


作者:乱码三千
链接:https://juejin.cn/post/7028744851805978638


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐