0x0 前言
前一章中,我们开始编写MBR,文章末实现了打印字符串并基于jmp $指令实现死循环。本节中,将继续实现MBR功能。
感谢大佬的帖子:
从0到-1写一个操作系统-0x02-MBR支持显卡 - 『软件调试区』 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn
0x1 利用IO进行打印原理
上一节中,我们的打印利用的是BIOS定义的中断。但是,由于进入保护模式前需要cli关中断,因而不可能一直使用BIOS中断。本节中我们直接通过硬件开放的端口,向外设输出数据,进行打印。
显示器作为外设,其开放的接口连接显卡。编程时,我们将数据写入显存中,后续工作交由显卡自动完成。此外,使用显卡进行输出的时候,字符需要用ASCII码表示,每个1字节。
显卡显存分布如下:
显卡的工作模式主要有以下三种:
文本模式:在这种模式下,显卡将显存中的内容解释为字符和相应的属性(如颜色和背景色)。每个字符占用显存的两个字节,一个字节表示字符的ASCII码,另一个字节表示字符的属性。在文本模式下,屏幕每行能显示80个字符,共25行,一共能显示80*25=2000个字符。
黑白显示模式:这是一种特殊的文本模式,只能显示黑白两色的文本。这种模式在早期的单色显示器上使用。
彩色显示模式:在这种模式下,显卡可以显示彩色的字符或图形。彩色文本模式下,每个字符占用显存的两个字节,一个字节表示字符的ASCII码,另一个字节表示字符的属性(包括前景色和背景色)。
这三种模式的显存地址空间不同,主要是由于历史原因和兼容性考虑。
0x2 利用IO进行打印实现
基于上述显卡接口使用方式,我们基于文本模式打印字符。对前面文章中的汇编指令进行修改,修改位置在代码中进行了注释:
SECTION MBR vstart=0x7c00
mov ax,cs
mov dx,ax
mov es,ax
mov ss,ax
mov fs,ax
mov sp,0x7c00
;使用文本模式,所以得把文本范围类的地址输入gs当作段基地址
mov ax,0xb800
mov gs,ax
mov ax,0x600
mov bx,0x700
mov cx,0
mov dx,0x184f
int 0x10
;利用IO进行打印
mov byte [gs:0x00], 'p'
mov byte [gs:0x01], 0x94
mov byte [gs:0x02], 'e'
mov byte [gs:0x03], 0x94
mov byte [gs:0x04], 'i'
mov byte [gs:0x05], 0x94
mov byte [gs:0x06], 'w'
mov byte [gs:0x07], 0x94
mov byte [gs:0x08], 'i'
mov byte [gs:0x09], 0x94
mov byte [gs:0x0a], 't'
mov byte [gs:0x0b], 0x94
mov byte [gs:0x0c], 'h'
mov byte [gs:0x0d], 0x94
mov byte [gs:0x0e], 'h'
mov byte [gs:0x0f], 0x94
mov byte [gs:0x10], 'a'
mov byte [gs:0x11], 0x94
mov byte [gs:0x12], 'o'
mov byte [gs:0x13], 0x94
jmp $
times 510-($-$$) db 0
db 0x55,0xaa
其中,如下两行代码指定了段基址,方便从代表文本模式的0xb800计算写入位置
mov ax,0xb800
mov gs,ax
后续打印中,对每个待输出字符,第一字节为字节本身,第二字节指定了背景色和字符颜色。
进行编译并插入磁盘第一扇区中
运行效果符合预期