📄 setup.asm
字号:
;文件名: setup.asm
;作 者; 谢煜波
;Emailv: 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 1024 ;SYSTEM的大小1KB,此值必须是 512 的倍数
;实际值可以不符
;下面定义临时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 ;段限(0x3fff+1)*4KB=64KB
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
mov dl , [0]
mov ch , 0
mov cl , 1 + 1 + SETUPSIZE / 512 ;system所在的启始扇区
;第一个1是指从1开始记数
;第二个1是boot所占扇区数
mov al , SYSTEMSIZE / 512 ;读入扇区数( 2个扇区共1KB )
int 0x13
jc .readfloopy
;下面将读入的system搬移到0x00000位置
cld
mov si , SETUPOFFSET + SETUPSIZE
mov ax , SYSTEMSEG
mov es , ax
mov di , SYSTEMOFFSET
mov cx , SYSTEMSIZE / 4
rep movsd
;下面开始为进入保护模式而进行初始化工作
cli ;关中断
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
jmp dword 0x8:0x0
;-------------------------------------------------------------------------------------
times 1024-($-$$) db 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -