boot.asm代码做了以下三件事:
1)清空屏幕
2)加载模块
3)跳转到 SETUP_SEG
org BOOT_SEG
start:
cli
NMI_DISABLE
; enable a20 line
FAST_A20_ENABLE
sti
; set BOOT_SEG environment
mov ax, cs
mov ds, ax
mov ss, ax
mov es, ax
mov sp, BOOT_SEG ; 设 stack 底为 BOOT_SEG
call clear_screen
mov esi, SETUP_SECTOR
mov di, SETUP_SEG - 2
call load_module ; 加载 setup 模块
mov esi, LIB16_SECTOR
mov di, LIB16_SEG - 2
call load_module ; 加载 lib16 模块
mov esi, LONG_SECTOR ; 加载 long 模块
mov di, 0x9000 - 2
call load_module
mov ax, 0x1000
mov es, ax
mov esi, 0x9000
mov edi, 0
movzx ecx, WORD [0x9000-2]
db 0x67
rep movsb
mov esi, PROTECTED_SECTOR
mov di, PROTECTED_SEG - 2
call load_module ; 加载 protected 模块
mov esi, LIB32_SECTOR
mov di, LIB32_SEG - 2
call load_module ; 加载 lib32 模块
jmp SETUP_SEG ; 转到 SETUP_SEG
next:
jmp $
每个模块的前两个字节是该模块的大小,我们org - 2,然后定义一个dw数据,后面才是函数的入口地址,代码如下,很好理解。
; boot.asm
; Copyright (c) 2009-2012 mik
; All rights reserved.
; 这是一个空白模块示例,设为 setup 模块
; 用于写入磁盘的第 2 个扇区 !
;
%include "..\inc\support.inc"
;
; 模块开始点是 SETUP_SEG - 2,减 2 是因为要算上模块头的存放的“模块 size”
; load_module 加载到 SETUP_SEG-2,实际效果是 SETUP 模块会被加载到“入口点”即:setup_entry
;
org SETUP_SEG - 2
;
; 在模块的开头 word 大小的区域里存放模块的大小,
; load_module 会根据这个 size 加载模块到内存
SETUP_BEGIN:
setup_length dw (SETUP_END - SETUP_BEGIN) ; SETUP_END-SETUP_BEGIN 是这个模块的 size
setup_entry: ; 这是模块代码的入口点。
message db 'the message from setup module at sector 20...', 13, 10, 0
times 512-($-$$) db 0
SETUP_END:
; end of setup