setup.s作为承上启下,主要功能是CPU模式切换、加载内核代码并最终跳转到内核代码。
;功能
;1. 获取当前内存大小和硬盘参数
;2. 从硬盘加载内核代码到内存地址: 0x1000:0000,默认内核代码最大不超过64K
;3. 配置 8259a
;4. 配置gdt表并进入到32bits保护模式并跳转到内核的kernel_start()函数入口
代码:
entry start
start:
;setup.s由boot.s代码跳转过来的,所以此时CS寄存器的值自动变为0x9020
;为了能访问setup.s的数据内容,也需要刷新DS,ES寄存器为0x9020
mov ax, cs
mov ds, ax
mov es, ax
;检查当前内存大小,使用bios 中断int 0x15。该方法的缺点是:最大支持64M内存
;检查结果存放在memort_size标签对应的内存地址中。
mov ah, #0x88
mov al, #0x0
int 0x15
mov [memory_size], ax
;检查硬盘CHS参数,并把参数存放在hd_info标签处
;只支持CHS模式,只支持第一个硬盘,第一个硬盘参数存放的物理地址记录在中断向量0x41中,即: 0x41*4 = 0x0000:0104地址处
;源地址 ds:si = 0x0000:0104
mov ax, #0x0000
mov ds, ax
lds si, [4*0x41]
;目的地址 es:di = 0x9020:[hd_info]
mov di, #hd_info
mv cx, #0x10 ;复制长度
rep
movsb
;恢复ds为0x9020
mov ax, cs
mov ds, ax
;打印load kernel....信息
mov si, #msg
call #print_msg
;准备加载内核代码,内核代码从磁盘的第4个扇区开始存放
load_kernel:
;初始化 current_track and current_sector
mov al, #0x0
mov byte [current_track], al
mov al, #0x4
mov byte [current_sector], al
;读取 kernel_sectors,这个值的大小可以在建立内核image的时候可以调整
mov al, byte [kernel_sectors]
push ax
;设置目的地址为0x1000:0000,保证当前内核文件大小必须小于64kBytes
mov ax, #0x1000
mov es, ax
xor bx, bx
xor dx, dx
mov dl, #0x0
mov dh, #0x0