自己动手写操作系统(开篇)

在 开篇一文中,我们实现了简单的通过使用 8086 汇编语言在裸机(没有安装操作系统的机器)上打印显示了一行文本信息,当然 8086 汇编语言给我们提供了好几种方式来显示,下面我们通过代码来实现其他几种文本的显示。


我们知道 8086 可以访问 1MB 内存。 其中:

0x00000 ~ 0x9FFFF 属于常规内存,由内存条提供;

0xF0000 ~ 0xFFFFF 由主板上的一个芯片提供,也就是 ROM-BIOS.

这样一来,中间还有320KB的空洞,也就是0xA0000 ~ 0xEFFFF 的区域, 传统上,这段地址空间由特定的外围设备来提供,其中就包括显卡,由于历史原因,个人计算机在加电自检后都会把自己初始化到 80 * 25 的文本模式,这种模式下,屏幕上可以显示25行,每行80个字符,每屏总共 2000 个字符。

0xB8000~0xBFFFF 这段物理地址空间,都留给显卡的,由显卡来提供,用来显示文本。




java 操作系统运行 java编写的操作系统_自己动手写操作系统

文本模式下显存的位置



通过操作显存来填满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

编译运行效果如下:




java 操作系统运行 java编写的操作系统_重复文本显示不同颜色js_02


说明:

其实就是在物理内存地址为:0xb8000 开始的地方填充了4000个字节

分别填入 0x31 0x04 重复 2000次。


java 操作系统运行 java编写的操作系统_java 操作系统运行_03

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


java 操作系统运行 java编写的操作系统_重复文本显示不同颜色js_04


当然也可以直接写入到显存中来实现。

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 会改变光标的位置.