您的位置:首页 > 其它

[翻译]如何用汇编创建一个基础内核 (二)

2011-03-11 23:28 253 查看
原文是 OSDev Wiki上的一个 Tutorials 文章。

1,第一个启动扇区

2,使用BIOS写消息

3,看看机器码

4,不用BIOS向屏幕打印输出

5,中断

6,进入保护模式

7,非实模式

8,32 位打印输出

附录A,更多资讯



2,使用BIOS写消息

快速回顾:

(1)BIOS加载的启动扇区大小是512字节

(2)在磁盘中启动扇区中的代码被BIOS 加载的地址位于0000:7C00

(3)机器在实模式下启动

(4) 应该清楚:CPU是可以给中断的,除非你明确使用了cli的汇编指令

许多(不是所有)BIOS中断预期是会用实模式下的段值来填充DS。这就是为什么许多BIOS中断在保护模式下

不会起作用的原因。所以当你想使用 int 10h/ah=0eh 去几屏幕打印字符,你需要确保你为打印字符所设置的

seg:offset 的值是正确的。

在实模式下,地址如些计算: segment*16+offset。 由于偏移地址可以比16大,所以会有许多的 segment offset

对是指向同一地址的。例如:一些时候说加载器是从0000:7C00处开始加载,当然,也有人说是从 07C0:0000处开始

加载。事实上,这两个是同一个地址: 16*0x0000 + 0x7c00 = 16*0x7C0 + 0x0000 = 0x7C00。

无论你使用0000:7C00 还是 07C0:0000 都是可以的,但你当你使用 org 时,你得清楚发生了什么事情。默认地,

原始二进制代码在一开始的偏移是0。若当你需要时,你可以改变这个偏移值,并使它生效。例如,下面的代码段是

从0X7C0处开始

; boot.asm
2 mov ax, 0x07c0
3 mov ds, ax
4
5 mov si, msg
6 ch_loop:lodsb
7 or al, al
8 jz hang
9 mov ah, 0x0E
int 0x10
jmp ch_loop

hang:
jmp hang

msg db 'Welcome to Macintosh', 13, 10, 0
times 510-($-$$) db 0
db 0x55
db 0xAA

下面是一个 ORG 版本。这次, 从段址0处访问消息 。请留意你仍需要告诉DS怎么设置值:

1
2 org 0x7c00
3 xor ax, ax ; make it zero
4 mov ds, ax
5
6 mov si, msg
7 ch_loop:lodsb
8 or al, al ; zero=end of string
9 jz hang ; get out
mov ah, 0x0E
int 0x10
jmp ch_loop

hang:
jmp hang

msg db 'Welcome to Macintosh', 13, 10, 0

times 510-($-$$) db 0
db 0x55
db 0xAA

过程版本。为了节省空间,典型地使用过程,像下面,在代码中使用 call / ret

1 org 0x7c00
2 xor ax, ax ;make it zero
3 mov ds, ax
4
5 mov si, msg
6 call bios_print
7
8 hang:
9 jmp hang

msg db 'Welcome to Macintosh', 13, 10, 0

bios_print:
lodsb
or al, al ;zero=end of str
jz done ;get out
mov ah, 0x0E
int 0x10
jmp bios_print
done:
ret

times 510-($-$$) db 0
db 0x55
db 0xAA

由于一些无法解释的原因,在加载SI,然后跳到过程时,我总会遇到bug。幸运的是,可以像我这样在NASM中

使用宏来传递一个参数。

1 %macro BiosPrint 1
2 mov si, word %1
3 ch_loop:lodsb
4 or al, al
5 jz done
6 mov ah, 0x0E
7 int 0x10
8 jmp ch_loop
9 done:
%endmacro

org 0x7c00
xor ax, ax
mov ds, ax

BiosPrint msg

hang:
jmp hang

msg db 'Welcome to Macintosh', 13, 10, 0

times 510-($-$$) db 0
db 0x55
db 0xAA

如果,你觉得代码过长而不好理解,你可以把它分到不同的文件中去,然后在文件中包含在代码开头:

jmp main

%include "othercode.inc"

main:
; ... rest of code here

不要忘记了在一开始就调用 jmp main,不然的话,会顺序启动其它一些随机代码了。

(第二篇END)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: