【发布时间】:2022-11-02 04:20:23
【问题描述】:
我知道这个问题被问了很多,但我找到的每个答案都对我不起作用。我正在尝试加载我的操作系统的stage 2,位于我的图像文件的第二个扇区(0x200)
这是我尝试使用的代码:
bits 16 ; Starting at 16 bits
org 0x0 ; And starting at 0
jmp main ; Hop to main!
; TODO: copy comment from prev. loader
; args: SI
print:
lodsb ; Load the next/first character to AL
or al, al ; Is it 0?
jz donePrint ; Yes - Done.
mov ah, 0eh ; No - keep going.
int 10h ; Print character.
jmp print ; Repeat
donePrint:
ret ; Return
; todo: args
readSector:
mov ah, 02h
mov al, 1
mov dl, 0x80
mov ch, 0
mov dh, 0
mov cl, 2
mov bx, 0x500
int 13h
jnc good
jmp fail
main:
; First, setup some registers.
cli ; Clear interrupts
mov ax, 0x07C0 ; Point all registers to segment
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
; Create the stack(0x0000-0xFFFF).
mov ax, 0x0000
mov ss, ax ; Point SS to 0x0000
mov sp, 0xFFFF ; Stack pointer at 0xFFFF
sti ; Restore interrupts
mov si, LOADING
call print
call readSector
fail:
mov si, FAILURE_MSG
call print
good:
mov si, LOADOK
call print
jmp 0x500
LOADING db 0x0D, 0x0A, "Booting loader...", 0x0D, 0x0A, 0x00
FAILURE_MSG db 0x0D, 0x0A, "ERROR: Press any key to reboot.", 0x0A, 0x00
LOADOK db 0x0D, 0x0A, "load ok", 0x0A, 0x00
TIMES 510 - ($-$$) DB 0
DW 0xAA55
但它只是引导循环。我尝试了其他解决方案无济于事。我究竟做错了什么? 如果我需要更新问题,请告诉我。
谢谢!
编辑#1:根据 Sep Roland 的回答,我更新了我的代码,但它仍然无法正常工作。如果有任何帮助,我会将更新的代码放在这里。此外,如果要求,我可以发布我的第二阶段代码。它应该使用 0x500 作为 org.新代码:
bits 16 ; Starting at 16 bits
org 0x0 ; And starting at 0
jmp main ; Hop to main!
; TODO: copy comment from prev. loader
; args: SI
print:
lodsb ; Load the next/first character to AL
or al, al ; Is it 0?
jz donePrint ; Yes - Done.
mov ah, 0eh ; No - keep going.
int 10h ; Print character.
jmp print ; Repeat
donePrint:
ret ; Return
; todo: args
readSector:
mov ah, 02h
mov al, 1
mov ch, 0
mov dh, 0
mov cl, 2
mov bx, 0x500
int 13h
jnc good
jmp fail
main:
; First, setup some registers.
cli ; Clear interrupts
mov ax, 0x07C0 ; Point all registers to segment
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
; Create the stack(0x0000-0xFFFF).
mov ax, 0x0000
mov ss, ax ; Point SS to 0x0000
mov sp, 0xFFFE ; Stack pointer at 0xFFFE
sti ; Restore interrupts
mov si, LOADING
call print
call readSector
fail:
mov si, FAILURE_MSG
call print
end:
cli
hlt
jmp end
good:
mov si, LOADOK
call print
jmp 0x07C0:0x0500
LOADING db 0x0D, 0x0A, "Booting loader...", 0x0D, 0x0A, 0x00
FAILURE_MSG db 0x0D, 0x0A, "ERROR: Press any key to reboot.", 0x0A, 0x00
LOADOK db 0x0D, 0x0A, "load ok", 0x0A, 0x00
TIMES 510 - ($-$$) DB 0
DW 0xAA55
编辑#2:发布包括gdt.inc 的第二阶段代码,因为有人提到LGDT 可能导致了问题:
主要代码(某些部分已被删除,但它们不是必需的,如字符串)
bits 16 ; We start at 16 bits
org 0x500 ; We are loaded in at 0x500
jmp main ; Jump to main code.
; ----------------------------------------
; Includes
; ----------------------------------------
%include "include/stdio.inc"
%include "include/gdt.inc"
%include "include/a20.inc"
; ---------------------------------------
; Data and strings
; ---------------------------------------
stringhidden db "Not showing string.", 0x0D, 0x0A, 0x00
stringhidden db "Not showing string.", 0x0D, 0x0A, 0x00
; ---------------------------------------------------------------------
; main - 16-bit entry point
; Installing GDT, storing BIOS info, and enabling protected mode
; ---------------------------------------------------------------------
main:
; Our goal is jump to main32 to become 32-bit
; Setup segments and stack
cli ; Clear interrupts
xor ax, ax ; Null segments AX, DS, and ES
mov ds, ax
mov es, ax
mov ax, 0x9000 ; Stack begins at 0x9000-0xFFFF
mov ss, ax
mov sp, 0xFFFF ; Stack pointer is 0xFFFF
sti ; Enable interrupts
; Install the GDT
call installGDT ; Install the GDT
; Enable A20
call enableA20_KKbrd_Out ; Enable A20 through output port
; Print loading messages
mov si, msg1
call print16 ; Print the message
mov si, msg2 ; A message
call print16 ; Print the message
; Enter protected mode
cli ; Clear interrupts
mov eax, cr0 ; Set bit 0 in CR0--ENTER protected mode
or eax, 1
mov cr0, eax
jmp CODE_DESC:main32 ; Far jump to fix CS
; We can't re-enable interrupts because that would triple-fault. This will be fixed in main32.
bits 32 ; We are now 32 bit!
%include "include/stdio32.inc"
main32:
; Set registers up
mov ax, 0x10 ; Setup data segments to 0x10(data selector)
mov ds, ax
mov ss, ax
mov es, ax
mov esp, 90000h ; Stack begins from 90000h
call clear32 ; Clear screen
mov ebx, MSGHIDDEN ; Setup params for our message
call puts32 ; Call puts32 to print
cli ; Clear interrupts
hlt ; Halt the processor
LGDT 代码:
%ifndef __GDT_INC_67343546FDCC56AAB872_INCLUDED__
%define __GDT_INC_67343546FDCC56AAB872_INCLUDED__
bits 16 ; We are in 16-bit mode
; -----------------------------------------
; installGDT - install the GDT
; -----------------------------------------
installGDT:
cli ; Clear interrupts
pusha ; Save the registers
lgdt [toc] ; Load GDT into GDTR
sti ; Re-enable interrupts
popa ; Restore registers
ret ; Return!
; ----------------------------------------
; Global Descriptor Table data
; ----------------------------------------
gdt_data:
dd 0 ; Null descriptor
dd 0
; GDT code starts here
dw 0FFFFh ; Limit low
dw 0 ; Base low
db 0 ; Base middle
db 10011010b ; Access
db 11001111b ; Granularity
db 0 ; Base high
; GDT data starts here(mostly same as code, only difference is access)
dw 0FFFFh ; Limit low, again.
dw 0 ; Base low
db 0 ; Base middle
db 10010010b ; Access - different
db 11001111b ; Granularity
db 0
gdt_end:
toc:
dw gdt_end - gdt_data - 1
dd gdt_data ; Base of GDT
; Descriptor offsets names
%define NULL_DESC 0
%define CODE_DESC 0x8
%define DATA_DESC 0x10
; End of GDT code.
%endif ;__GDT_INC_67343546FDCC56AAB872_INCLUDED__
【问题讨论】:
-
你能提供你的第二阶段吗?第二阶段的任何机会都是
lgdt。如果是这样,我可以想到为什么会失败。如果您使用lgdt作为进入保护模式的一部分(我猜),您可能会遇到由 DS != 0 引起的问题,并且 GDTR 需要线性地址,这需要修复将 0x7c00 添加到基数GDTR 中 GDT 的地址。通常使用 0x500 的人打算将第二阶段放在 0x0000:0x0500。看到 0x07c0:0x0500 是物理地址 0x8100 有点不寻常。 -
如果 LGDT 有问题,则可能还必须调整阶段 2 中的 far jmp 以进入保护模式。如果您可以向我们展示第 2 阶段,我们可能会解决您的问题。我不相信您看到的问题与引导扇区有关。
-
我将在当天晚些时候更新第 2 阶段的代码。是的,这可能是问题所在,正在调用 LGDT 和其他方法。
-
我个人会在引导加载程序中设置
org 0x7c00,在第二阶段设置org 0x500,然后将所有段(ES、DS 设置为0 而不是0x07c0)。这也会将您的第二阶段加载到 0x0000:0x0500 而不是 0x07c0:0x0500。使用非零段带有可以通过使用 0 来避免的陷阱(包括您在 GDT 中遇到的问题等)。 -
@MichaelPetch 它奏效了!谢谢!您可以将此作为答案发布,以便我接受吗?
标签: assembly nasm x86-16 bootloader osdev