问题描述
我目前正在开发一个简单的操作系统,我决定从头开始编写。 在引导加载程序的第二阶段,当我切换到保护模式时,它在切换后立即卡住,并且模拟器 (QEMU) 重新启动。
这是引导加载程序阶段 1:
org 0x7C00
;SEGMENTS
;bootloadter stage 1: 0x0000:0x7C00
;bootloader stage 2: 0x07E0:0x0100
;public data segment: 0x08E0:0x0000
;gdt: 0x1000:0x0000
;idt: 0x1000:0x0200
;kernel: 0x2000:0x0000
init:
;sets up the temporary data segment
xor ax,ax
mov ds,ax
;set up the stack
xor ax,ax
mov ss,ax
mov sp,0x7C00
<<save the drive number>>
;reset the drive
call drive_reset
;loads IDT but does not load the idtr until we're in protected mode
call load_idt
;loads GDT
call load_gdt
lgdt [0x9E]
call load_stage2
call _wait
jmp 0x07E0:0x0100
jmp $
load_data_segment:
<<loads the shared data segment from disk>>
ret
load_stage2:
<<loads second stage from disk>>
ret
print:
<<print function>>
boot_failure:
<<boot failure function (alerts the user and halts the system)>>
_wait:
<<wait function (wait for the user to press a key)>>
reboot:
<<reboot function>>
;loads the initial gdt table from sector 9 to 0x1000:0x0000 (512 byte)
load_gdt:
mov si,0x00
call print
mov ah,0x2 ;subroutine
mov al,0x1 ;numbers of sectors to be read
mov dl,[0xAA] ;drive number
mov ch,0 ;cylinder number
mov dh,0 ;head number
mov cl,9 ;start sector (the first sector has index 1)
mov bx,0x1000 ;segment
mov es,bx
mov bx,0x0000 ;segment offset
int 0x13 ;drive low level routines
jc process_error
call drive_reset
call process_done
ret
;loads the initial idt table from sector 10 to 0x1000:0x0200 (512 bytes)
load_idt:
mov si,0x10
call print
mov ah,0x4 ;numbers of sectors to be read
mov dl,0xA ;start sector (the first sector has index 1)
mov bx,0x200 ;segment offset (512 bytes),right after gdt
int 0x13 ;drive low level routines
jc process_error
call drive_reset
call process_done
ret
process_done:
<<print "[DONE]">>
process_error:
<<print "[ERROR]" and halts the system>>
drive_reset:
<<drive reset function>>
drive_number: db 0
times 510-($-$$) db 0x0
dw 0xAA55
引导加载程序阶段 2:
org 0x0100
;segment 0x07E0
;offset 0x0100
init:
cli
;sets up the data segment
mov ax,0x08E0
mov ds,ax
;sets up the stack
mov ax,0x07E0
mov ss,0x0100
sti
;loads the kernel
mov si,0x63 ;loading kernel...
call print
call load_kernel
call process_done
;enable A20
checkA20:
mov si,0x20 ;checking A20...
call print
call A20_test
cmp ax,1
je A20_enabled_func
jmp A20_disabled_func
continue: ;return point from A20 procedures
jmp enable_protected
_wait:
mov si,0xB7
call print
mov ah,0
int 0x16
ret
A20_disabled_func:
<<calls enable_A20 procedure and jumps to 'continue'>>
A20_enabled_func:
<<print "ENABLED">>
print:
<<print function>>
process_done:
<<prints "[DONE]">>
process_error:
<<prints "[ERROR]" and halts the system>>
A20_test:
pushf
push ds
push es
push di
push si
cli
xor ax,ax
mov es,ax
mov di,0x0500
mov ax,0xffff
mov ds,ax
mov si,0x0510
mov al,byte es:[di]
push ax
mov al,byte ds:[si]
push ax
mov byte es:[di],0x00
mov byte ds:[si],0xFF
cmp byte es:[di],0xFF
pop ax
mov byte ds:[si],al
pop ax
mov byte es:[di],al
mov ax,0
je A20_test_exit
mov ax,1
A20_test_exit:
pop si
pop di
pop es
pop ds
popf
ret
enable_A20:
cli
call a20wait
mov al,0xAD
out 0x64,al
call a20wait
mov al,0xD0
out 0x64,al
call a20wait2
in al,0x60
push eax
call a20wait
mov al,0xD1
out 0x64,al
call a20wait
pop eax
or al,2
out 0x60,0xAE
out 0x64,al
call a20wait
sti
ret
a20wait:
in al,0x64
test al,2
jnz a20wait
ret
a20wait2:
in al,1
jz a20wait2
ret
load_kernel:
mov ah,21 ;start sector (the first sector has index 1)
mov bx,0x2000 ;segment
mov es,0x0 ;segment offset
int 0x13 ;drive low level routines
jc process_error
ret
enable_protected:
mov si,0x43 ;switching to protected mode...
call print
call _wait
mov eax,cr0
or eax,1
mov cr0,eax ;--------HERE IS THE PROBLEM--------
bits 32
mov ax,0x8
mov cs,ax
jmp 0x2000
times 2560-($-$$) db 0xAE
我在 x86 架构上使用 nasm 编译器和 qemu 作为模拟器。 我感谢任何读到这里而没有改变主意的人:D 我希望我可以发布所有内容,但该网站说它看起来像垃圾邮件...
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)