2

自己动手从零写桌面操作系统GrapeOS系列教程——17.用汇编语言清空屏幕 - 成宇佳

 1 year ago
source link: https://www.cnblogs.com/chengyujia/p/17229428.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

学习操作系统原理最好的方法是自己写一个简单的操作系统。


在QEMU中会默认输出一些字符,有时候会干扰我们自己输出的字符。一个比较好的办法是向将屏幕清空,再输出我们想要输出的字符。下面就来学习如何清空屏幕。

一、清空屏幕

其实清空屏幕的原理很简单,就是将屏幕写满空格就行了。
下面来实战。mbr8.asm代码如下:

;定义常量(作用和C语言中的#define一样)
VIDEO_CHAR_MAX_COUNT equ 2000 ;默认屏幕最多显示字符数。

org 0x7c00

;初始化段寄存器
mov ax,0xb800
mov es,ax ;本程序中es专用于指向显存段

;清屏
call func_clear_screen

stop:
hlt
jmp stop 

;清屏函数(将屏幕写满空格就实现了清屏)
;输入参数:无。
;输出参数:无。
func_clear_screen:
mov ah,0x00 ;黑底黑字
mov al,' '  ;空格
mov cx,VIDEO_CHAR_MAX_COUNT ;循环控制
.start_blank:
mov bx,cx ;以下3行表示bx=(cx-1)*2 
dec bx
shl bx,1
mov [es:bx],ax ;[es:bx]表示字符对应的显存地址(从屏幕右下角往前清屏)
loop .start_blank
ret

times 510-($-$$) db 0
db 0x55,0xaa

编译运行截图如下:

343777-20230318095332048-1247870597.png
343777-20230318095339781-296441025.png
343777-20230318095346749-765602308.png

从上面QEMU截图可以看到,之前QEMU默认输出的字符已经没有了,屏幕清空的很干净。

二、在清空的屏幕上输出字符串

一般我们都是先清空屏幕,再输出自己想要输出的字符串。
下面我们来看mbr9.asm的代码:

;定义常量(作用和C语言中的#define一样)
VIDEO_CHAR_MAX_COUNT equ 2000 ;默认屏幕最多显示字符数。

org 0x7c00 ;如果没有该行将无法正确打印要显示的字符串

;初始化段寄存器
mov ax,cs
mov ds,ax ;ds指向与cs相同的段
mov ax,0xb800
mov es,ax ;本程序中es专用于指向显存段

;清屏
call func_clear_screen

;打印字符串
mov si,string1
mov di,0 ;在屏幕第1行显示
call func_print_string

stop:
hlt
jmp stop 

;清屏函数(将屏幕写满空格就实现了清屏)
;输入参数:无。
;输出参数:无。
func_clear_screen:
mov ah,0x00 ;黑底黑字
mov al,' '  ;空格
mov cx,VIDEO_CHAR_MAX_COUNT ;循环控制
.start_blank:
mov bx,cx ;以下3行表示bx=(cx-1)*2 
dec bx
shl bx,1
mov [es:bx],ax ;[es:bx]表示字符对应的显存地址(从屏幕右下角往前清屏)
loop .start_blank
ret

;打印字符串函数。
;输入参数:ds:si,di。
;输出参数:无。
;ds:si 表示字符串起始地址,以0为结束符。
;di 表示字符串在屏幕上显示的起始位置(0~1999)。
func_print_string:
mov ah,0x07 ;ah表示字符属性,0x07表示黑底白字。
shl di,1 ;乘2(屏幕上每个字符对应2个显存字节)。
.start_char: ;以点开头的标号为局部标号,完整形式是 func_print_string.start_char,但在同一个全局标号func_print_string内部不需要写完整形式。
mov al,[si]
cmp al,0
jz .end_print
mov [es:di],ax ;将字符和属性放到对应的显存中。
inc si
add di,2
jmp .start_char
.end_print:
ret

string1:db "Hello GrapeOS!",0

times 510-($-$$) db 0
db 0x55,0xaa

mbr9.asm其实就是将mbr8.asm和mbr7.asm合并了一下。
下面来看编译运行截图:

343777-20230318095404981-1213838075.png
343777-20230318095414455-839070562.png
343777-20230318095421506-1119828213.png

从上面的QEMU截图中可以看到,我们在清空的屏幕上第一行显示了字符串“Hello GrapeOS!”,这就是我们想要的效果。


本讲视频版地址:https://www.bilibili.com/video/BV1DD4y137ET/
本教程代码和资料:https://gitee.com/jackchengyujia/grapeos-course
GrapeOS操作系统QQ群:643474045

作者:成宇佳
博客主页:http://www.cnblogs.com/chengyujia/
欢迎转载,但请保留作者和本文链接,谢谢!
欢迎在下面的评论区与我交流。
如果觉得写的不错,请点击下面的“推荐”按钮,让我更有动力写出更好的文章。

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK