清理屏幕

上一节我们通过在显存地址直接写入字符,打印除了“hello”。但因为显存内存储着BIOS启动过程中的一些显示信息,所以屏幕看着很乱。这一节我们在打印字符之前,先讲显存内的内容清空,再进行打印,这样看着清爽些。

清空显存,当然有个笨办法,就是像打印“hello”一样,从0xb8000开始,向显存写入空白或不可见字符。但这个比较累。还有一个办法就是调用bios提供的int 10中断。

int10中断

org 07c00h         ; 告诉编译器程序加载到7c00处

;----中断10h,卷屏,实现清屏
mov ax, 0x0600
mov bx, 0x0700
mov cx, 0
mov dx, 0x184f
int 0x10

;----直接往显存中写数据
mov ax, 0xb800
mov gs, ax
mov byte [gs:0x00],'h'
mov byte [gs:0x02],'e'
mov byte [gs:0x04],'l'
mov byte [gs:0x06],'l'
mov byte [gs:0x08],'o'

times 510-($-$$) db 0 ; 填充剩下的空间,使生成的二进制代码恰好为512字节
dw 0xaa55             ; 结束标志

以上代码中,我们先设置好参数,然后调用int 10中断,实现了清屏操作。效果如下:

hello

关于INT 10h的更多细节,可以看这里 wikipedia INT 10h

内存布局

启动后,BIOS通过int 19中断将第一个扇区对应的512字节拷贝至内存0x7c00处。那此时的内存布局是什么样子的呢?

ram_boot

如上图所示,点击电源键开机后,CPU处于实模式,即16位工作模式。但此时地址总线宽度为20位,最大寻址内存空间为2^20=1MB

实模式寻址

实模式下,CPU寻址方式为段基地址+段内偏移地址,即每个内存单元可以用两个16位寄存器的值拼接而成。寄存器为16位,可以表示的最大段内偏移量为2^16=64KB。CPU将16位段寄存器值左移4位得到段基地址,再加上段内偏移量,得到20位内存地址。