自己动手写操作系统(开篇)
在 开篇一文中,我们实现了简单的通过使用 8086 汇编语言在裸机(没有安装操作系统的机器)上打印显示了一行文本信息,当然 8086 汇编语言给我们提供了好几种方式来显示,下面我们通过代码来实现其他几种文本的显示。
我们知道 8086 可以访问 1MB 内存。 其中:
0x00000 ~ 0x9FFFF 属于常规内存,由内存条提供;
0xF0000 ~ 0xFFFFF 由主板上的一个芯片提供,也就是 ROM-BIOS.
这样一来,中间还有320KB的空洞,也就是0xA0000 ~ 0xEFFFF 的区域, 传统上,这段地址空间由特定的外围设备来提供,其中就包括显卡,由于历史原因,个人计算机在加电自检后都会把自己初始化到 80 * 25 的文本模式,这种模式下,屏幕上可以显示25行,每行80个字符,每屏总共 2000 个字符。
0xB8000~0xBFFFF 这段物理地址空间,都留给显卡的,由显卡来提供,用来显示文本。
文本模式下显存的位置
通过操作显存来填满2000个1
org 07c00h mov ax, cs mov ds, ax mov ax, 0xb800 ; //把 es 的值设置为 显存的位置 mov es, ax mov si, 1999;//要显示的字符个数 mov di, 0 ;//下标,把显存看成是一个数组 mov al, 0x31;//字符 ‘1’当然这里也可以直接写成 mov al, '1' 也是可以的 mov ah, 0x04;//颜色信息show: mov [es:di], ax add di, 2 dec si jns show jmp $times 510-($-$$) db 0dw 0xaa55
编译运行效果如下:
说明:
其实就是在物理内存地址为:0xb8000 开始的地方填充了4000个字节
分别填入 0x31 0x04 重复 2000次。
80 * 25 文本模式下的颜色表
字符打印: 一个字符一个字符的打印,直达遇见了 $ 符号后结束, 通过调用 int10h 实现
org 0x7c00 mov ax, cs mov es, ax mov ds, ax mov si, weldata call DispStr jmp $ DispStr: mov al, [si] cmp al, '$' je Disover mov ah, 0eh int 10h inc si jmp DispStr Disover:retweldata db 'Welcome Test Os!', '$'times 510-($-$$) db 0db 0x55,0xaa
这个程序的显示实现主要是靠: ax 的值和 int 10h 实现。
这里 ax 分为 ah 和 al , 其中 al 里面保存了要打印的字符,ah 的值设置为 0eh 是告诉 int 10h 执行的是字符打印(显示)功能。
ah 设置为不同的值,调用 int 10h 可以实现不同的功能。
具体可以参考网络博文:
打印字符 ,通过指定长度和调用 int 10h 实现
jmp near start showstr db 'Hello World!'start: mov ax, 0x7c0 mov ds, ax mov es, ax mov si, showstr mov cx, start - showstrdisp: mov al, [si] mov ah, 0xe int 10h inc si loop disp jmp $times 510-($-$$) db 0db 0x55, 0xaa
当然也可以直接写入到显存中来实现。
jmp near start showstr db 'Hello World!'start: mov ax, 0x7c0 mov ds, ax mov ax, 0xb800 mov es, ax mov si, showstr mov cx, start - showstr mov di, 0disp: mov al, [si] mov [es:di], al inc di mov byte[es:di], 0x07 inc di inc si loop disp jmp $times 510-($-$$) db 0db 0x55, 0xaa
说明:通过直接写入显存显示和调用 int 10h 来显示,在显示效果上有一个小小的区别 就是 ,通过直接写显存的方式来显示字符不会改变光标的位置,而调用 int 10h 会改变光标的位置.