📄 setup.asm
字号:
;setup.asm
;for pyos4
;xieyubo@126.com
;此setup程序完成boot未完成的启动工作,
;包括从BIOS中读出系统信息存放在指定位置
;初始化GDT,LDT表,完成从保护模式到实模式的转换
;实模式的代码也由此程序读入
[BITS 16]
[ORG 0x0100]
;-------------------------------------------------------------------------------------
jmp Main
;-------------------------------------------------------------------------------------
SETUPSEG equ 0x9000
SETUPOFFSET equ 0x0100
SETUPSIZE equ 1024 ;setup的大小 1KB , 必须是 512 的倍数
SYSTEMSEG equ 0x0000
SYSTEMOFFSET equ 0x0000
SYSTEMSIZE equ 16896 ;SYSTEM的大小 1KB ,此值必须是 512 的倍数,实际值可以不符
;10240 共 20个扇区 ( 10240 = 512 * 20 ),目前setup可接受的
;大小为 15 + 18 = 33个扇区,即 33 * 512 = 16896 个字节,
;如果 SYSTEMSIZE 值超过此字节数,将更改下面读入程序
;下面定义临时GDT表的描述符
;总共定义三个段,一个空段由intel保留,一个代码段,一个数据段
gdt_addr:
dw 0x7fff ;GDT表的大小
dw gdt ;GDT表的位置
dw 0x0009
gdt:
gdt_null:
dw 0x0000
dw 0x0000
dw 0x0000
dw 0x0000
gdt_system_code:
dw 0x3fff ;段限( 16K * 64KB = 64MB )
dw 0x0000
dw 0x9a00
dw 0x00c0
gdt_system_data:
dw 0x3fff
dw 0x0000
dw 0x9200
dw 0x00c0
;-------------------------------------------------------------------------------------
;等待键盘控制器空闲的子程序
Empty_8042:
in al , 0x64
test al , 0x2
jnz Empty_8042
ret
;-------------------------------------------------------------------------------------
Main:
;初始化寄存器,因为Bios中断及call会用到堆栈或ss寄存器
;在CPU启动或复位时是由BIOS初始化的,而现在进行了段转移,需要我们重新设置
mov ax , SETUPSEG
mov ds , ax
mov es , ax
mov ss , ax
mov sp , 0xffff
;-------------------------------------------------------------------------
;从BIOS中到底应读出哪些有用信息,现在还不确定,因此暂时跳过此功能块
;-----------------------------------------------
;0x90000 (1B): 保存启动驱动器号,由boot程序存入
;--------------------------------------------------------------------------
;下面读入system到setup程序的后面
;因为0x00000现在是放BIOS中断的地方,因此还不能直接将system读到0x00000处,否则将无法调用BIOS中断读入磁盘
.readfloopy:
mov ax , SETUPSEG
mov es , ax
mov bx , SETUPOFFSET + SETUPSIZE
mov ah , 2 ; 功能号 2 表示读磁盘扇区
mov dl , [0] ; 驱动器号
mov dh , 0 ; 0号磁头
mov ch , 0 ; 0磁道
mov cl , 1 + 1 + SETUPSIZE / 512 ;system所在的启始扇区( 第一个1是指从1开始记数,第二个1是boot所占扇区数)
; 目前内核大小超过1磁道 18扇区的容量,因此需要读入两个磁道,这里先读第一个磁道
mov al , 15 ;读入扇区数( 第一磁道还留有的扇区数 )
int 0x13
; 下面继续读入第二面的第一个磁道,共18扇区,因为前面中断的返回值修改了寄存器,因此必需重新设置
mov ax , SETUPSEG
mov es , ax
mov bx , SETUPOFFSET + SETUPSIZE + 15 * 512
mov ah , 2 ; 功能号 2 表示读磁盘扇区
mov dl , [0] ; 驱动器号
mov dh , 1 ; 1号磁头
mov ch , 0 ; 0磁道
mov cl , 1 ; 启始扇区1扇区
mov al , 18 ; 读入扇区数
int 0x13
jc .readfloopy
cli ;关中断
;下面将读入的system搬移到0x00000位置
cld
mov si , SETUPOFFSET + SETUPSIZE
mov ax , SYSTEMSEG
mov es , ax
mov di , SYSTEMOFFSET
mov cx , SYSTEMSIZE / 4
rep movsd
;下面开始为进入保护模式而进行初始化工作
lgdt [gdt_addr] ;载入gdt的描述符
;下面打开A20地址线
call Empty_8042
mov al , 0xd1
out 0x64 , al
call Empty_8042
mov al , 0xdf
out 0x60 , al
call Empty_8042
;下面设置进入32位保护模式运行
mov eax , cr0
or eax , 1
mov cr0 , eax
;下面建立临时堆栈,及临时寄存器值
mov ax , 0x10
mov ds , ax
mov es , ax
mov ss , ax
mov fs , ax
mov gs , ax
mov sp , 0xffff
jmp dword 0x8:0x0
;-------------------------------------------------------------------------------------
times 1024-($-$$) db 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -