我正在尝试编写加载下一个扇区的bootloader,并在启用a20后跳转执行它并进入保护模式。我创建了这段代码:
;NOTE: Im assuming that dl is hard drive number when executing bootloader
org 0x7C00
bits 16
jmp 0:kernel_load
;setup gdt
gdt_start:
gdt_null:
dd 0x0
dd 0x0
gdt_code:
dw 0xffff
dw 0x0
db 0x0
db 10011010b
db 11001111b
db 0x0
gdt_data:
dw 0xffff
dw 0x0
db 0x0
db 10010010b
db 11001111b
db 0x0
gdt_end:
gdt_descriptor:
dw gdt_end - gdt_start
dd gdt_start
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start
kernel_load:
;load kernel
reset:
mov ah,0
int 0x13
jc reset
mov ax,0x7E00
mov es,ax
xor bx,bx
read:
mov ah,0x02
mov al, 1
mov ch, 1
mov cl, 2
mov dh, 0
int 0x13
jc read
check_a20:
pushf
push ds
push es
push di
push si
cli
xor ax,ax
mov es,ax
not ax; ax = 0xFFFF
mov ds,ax
mov di,0x0500
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 check_a20_end
mov ax,1
check_a20_end:
pop si
pop di
pop es
pop ds
popf
ret
a20_enable:
inc bx
call check_a20
cmp ax,1
je a20_enable_end
mov ax,0x2401
int 0x15
call check_a20
cmp ax,1
je a20_enable_end
in al, 0x92
or al, 2
out 0x92, al
call check_a20
cmp ax,1
je a20_enable_end
jnz a20_enable
cmp bx,0x3
je boot_error
a20_enable_end:
;a20 enabled
;set gdt
lgdt[gdt_descriptor]
;clear registers
reload:
jmp 0x08:.reload_cs
.reload_cs:
mov ax,0x10
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
ret
;go to Pmode
mov eax, cr0
or al, 1
mov cr0, eax
;jump to kernel
jmp 0x7E00
boot_error:
mov bx,ErrorMSG
.print:
pusha
jmp .print1
.print1:
lodsb
or al,al
jz .print2
mov ah,0x0e
int 0x10
jmp .print1
.print2:
popa
ret
hlt
ErrorMSG db "Bootloader failure"
times 510-($-$$) db 0x0
db 0x55
db 0xAA
;==========
;Sector 2
;==========
bits 32
VIDEO_MEMORY equ 0xb8000
WHITE_ON_BLACK equ 0x0f
MSG db "working", 0
print:
pusha
mov edx, VIDEO_MEMORY
.loop:
mov al, [ebx]
mov ah, WHITE_ON_BLACK
cmp al, 0
je .done
mov [edx], ax
add ebx, 1
add edx, 2
jmp .loop
.done:
popa
ret
mov ebx,MSG
call print
hlt
当我试图在Bochs上打开这个代码时,它说“使用不存在的段寄存器7”。当我尝试在真实计算机上运行此代码时,计算机会生成三重故障并重新启动。
我将此代码基于以下来源:
启用A20 - http://wiki.osdev.org/A20
从磁盘加载扇区 - http://www.brokenthorn.com/Resources/OSDev5.html
转到保护模式 - http://wiki.osdev.org/Pmode
我不是真正的汇编程序员,所以如果有人能指出我生成Truple Fault的错误,我会非常感激,并解释为什么这段代码不起作用。
我还读到了在启用A20后我需要跳转到执行32位代码的地方,我试图交换加载内核,A20并进入保护模式但没有成功。
<小时/> 更新:
我对Jester评论做了一些改进。代码已经更新,但我仍然遇到问题。
现在只检查我是否使用过Jester的linked代码中的gdt
我还使用此来源来帮助GDT:http://wiki.osdev.org/GDT_Tutorial
Bochs现在可以开启,但它一直在说“使用不存在的段寄存器7”。在调试器模式下,它停留在mov bp, ??
答案 0 :(得分:0)
你的程序早期已经存在一些缺陷。
ret
无处可去!以下代码存在问题
call check_a20
cmp ax,1
je a20_enable_end
jnz a20_enable
cmp bx,0x3
je boot_error
它不会根据设置的最大重试次数重试! cmp bx,0x3
永远不会被执行。
为什么下一个代码块以ret
结尾?它不是一个子程序。
mov ax,0x10
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
ret
尝试显示您编写的mov bx,ErrorMSG
错误消息时,代码使用lodsb
来检索字符。您必须使用SI寄存器。