📄 multi-add-slic.asm
字号:
mov ax,bx ;BUFFER的偏移
mov [si+4h],ax
mov ax,ds ;BUFFER所在的段
mov [si+6h],ax
mov ax,HD_BlockNum-1 ;扇区号,这里是第HD_BlockNum号扇区,这里减1就等于标准INT 13H下的HD_BlockNum
mov [si+8h],ax ;在扩展INT 13H下,HD_BlockNum = 0是第一个扇区(MBR)
xor eax,eax
mov [si+0ah],ax
mov [si+0ch],eax
mov ah,dh ;入口:ds:si指向DAP的入口;DL驱动器号(80为第一个硬盘81为
mov dl,80h ;第二个);AH =功能代号 (42H=扩展读 42H=扩展写)
int 13h
sti
retn
;---------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------
;由于用堆栈保存读出来的数据的话,会导致INT 13H运行出错(INT 13H会对ES进行先进 -
;行打开写开关,然后关闭写开关的操作,如果ES指向SS(堆栈段)肯定会导致出错。 -
;ES:BX= 数据区中I/O缓冲区的地址 -
;AH=02H 读磁盘 | AL= 扇区数量 (这里读一个扇区[512字节=0x200H字节] -
;(CL)6,7 (CH)0~7=柱面 | (CL)0~5= 扇区号 ,这里的扇区号 = HD_BlockNum -
;DH= 磁头号/盘面 DL= 驱动器号 (80指第一个硬盘) -
;成功: AH=0, AL=读取的扇区数 失败: AH=错误码 -
;失败,CF=1,成功,CF = 0 -
;----------------------------------------------------------------------------------------
; cli
; mov cx,HD_BlockNum ;在标准INT 13H下,HD_BlockNum =0/1 都指向MBR,只不过一般用1来表示MBR
; mov ah,dh ;入口DH=读/写类型
; mov al,01h
; mov dx,0080h
; int 13h
; retn
;------------------------------------------------------------------------------------------------
;**************************************************************************************
INIT:
pushad ;这时的CS是可以写数据的!因为BIOS解压各模块时,各模块都设置为可写状态!
popad
retn
FIRST_RUN: ;显示选择的模块内容,并进行设置
pushad
mov dh,02h ;入口:无 ; 出口:无
call RW_HD_DATA
jb @fr_ext
and al,0f0h ; al
jne @fr_Ch ; xy
call CLEAR_SCREEN ; x x = 0,show message;=1,hide message !
mov si,MSG0 ; y y = value of choice !
call WRITE
call Display_Choosed_slic
mov si,MSG1
call WRITE
call WCRLF
CALL Check_KB_Input
@fr_ext:Call CLEAR_SCREEN
popad
retn
@fr_Ch: mov ah,01h ;如果设置为不显示选择的模块的内容,可以在BIOS自建后按F5重新进入设置画面。
int 16h
cmp ah, ENTER_PRESS_KEY ;ah = scan code
jne @fr_ext
call CLEAR_SCREEN
mov si,MSG2
call WRITE
call Enter_Choice
jmp @fr_ext
Display_Choosed_slic: ;显示选择的SLIC的品牌的信息
pushad
call read_hd_data ;入口:无 ; 出口:无
mov esi,SLIC+176h
add esi,eax
call WRITE
popad
retn
Check_KB_Input: ;检查键盘输入的按键,并进行相关的处理
pusha ;入口:无 ; 出口:无
mov ah,MSG1_SHOW_DELAY ;20*55ms
call DELAY
call Test_KB_Code
popa
retn
Test_KB_Code:
pusha
mov ah,01h
int 16h
cmp ah, ENTER_PRESS_KEY
je Is_The_Key
popa
retn
Is_The_Key:
call CLEAR_SCREEN
mov si,MSG2
call WRITE
call Enter_Choice
popa
retn
Enter_Choice: ;进入设置画面
pushad ;入口:无 ; 出口:无
EC_loop:
mov ah,0h
int 16h
cmp al,0dh ;0dH = 回车键的ASCII码
je Enter_Choice_exit
cmp al,30h
jl EC_loop
cmp al,39h
jg EC_loop
call DISPLAY_AL
sub al,30h
jmp ShowMSG_Choice
Enter_Choice_exit:
mov dh,02h
call RW_HD_DATA
ShowMSG_Choice:
and eax,00fh
push eax
call WCRLF
mov si,MSG2_C
call WRITE
@EC_KL: mov ah,0h
int 16h
cmp al,30h
je EC_K01
cmp al,31h
je EC_K01
jmp @EC_KL
EC_K01: call DISPLAY_AL
sub al,30h
mov bl,al
shl bl,4h
pop eax
add al,bl
call WCRLF
mov si,MSG_HD_1
call WRITE
call display_al_str
mov dh,03h
call RW_HD_DATA ;Input eax ,only use al,others set to 0 !
jb write_data_wrong
call WCRLF
mov si,MSG3
call WRITE
@EC_EXT:mov ah,50h ; 80 * 55 ms =4400 ms
call DELAY
call CLEAR_SCREEN
popad
retn
write_data_wrong: ;显示写硬盘出错的信息
call WCRLF ;入口:无 ; 出口:无
mov si,MSG_WRONG_1
call WRITE
mov al,ah
call display_al_str
call WCRLF
jmp @EC_EXT
;*************************************************************************************************************
BOOTSTRAP: ;这时的CS是绝对不可以写数据!必须另外想办法写!可以用堆栈!
pushad ;必须使用BOOTSTRAP,是因为,ACPI很大程度上是在该PCI模块运行后,才生成的。
push ds ;而且,只有在BOOTSTRAP运行的情况下,才可以正常的读/写硬盘
push es ;经过多次的失败,证明了必须用BOOTSTRAP来解决!
xor ecx,ecx
call enableA20 ;开启A20地址总线
push ecx
mov al,1
call setRealMode ;设置实模式的状态
call FIRST_RUN
call main
pop ecx
cmp cl,01h
je BOT_EXT
call disableA20 ;关闭A20地址总线
BOT_EXT:pop es
pop ds
popad
retf ;return to this rom's header
enableA20: ;开启A20地址总线
in al,92h ;入口;cl ; 出口:cl
test al,02h ;判断A20是否在执行该模块时就已经被开启了
je OP_A20 ;如果不是,就跳走,打开A20
mov cl,01h
retn
OP_A20: or al,02h
out 92h,al
retn
disableA20: ;关闭A20地址总线
in al,92h ;入口:无 ; 出口:无
and al,0fdh
out 92h,al
retn
setRealMode: ;设置实模式的状态
push eax ;入口:al ; 出口:ds,es
cli ;关闭中断
;--------------------下面使用堆栈的方法因为部分AWARD主板的8800:AE00等区域是只读的,所以必须用回堆栈---------
xor eax,eax
xor ecx,ecx ;计算cs:GDT1的物理地址,用于LGDT
mov ax,cs ;
shl eax,4h ;
mov cx,GDT1 ;这里使用堆栈操作,可以不用考虑不可以改写伪GDTR的值的问题
add eax,ecx
push eax
mov ax,GDTR_LEN
push ax
mov di,sp ;这里用堆栈来保存伪GDTR的值
add sp,6h ;恢复原来的堆栈指针!6h = 伪GDTR的长度
lgdt [ss:di] ;如果PC反复重启,绝大多数情况,是因为GDTR没有设置好。
;-----------------------------------------------------------------------------------------------------------
mov eax,cr0
or al,1 ;将cr0的0位设置为1,就进入了保护模式
mov cr0,eax ;进入保护模式
jmp pm_flush_queue
pm_flush_queue:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -