32位程序集引导加载程序可以在VM/qemu中工作,但不能在真正的PC上工作



我编码了这个小型引导加载程序,它在32位保护模式下向屏幕打印单个字符:

bits 16
org 0x7c00
jmp boot
times 3-($-$$) db 0x90   ; Support 2 or 3 byte encoded JMPs before BPB.
; Dos 4.0 EBPB 1.44MB floppy
OEMname:           db    "mkfs.fat"  ; mkfs.fat is what OEMname mkdosfs uses
bytesPerSector:    dw    512
sectPerCluster:    db    1
reservedSectors:   dw    1
numFAT:            db    2
numRootDirEntries: dw    224
numSectors:        dw    2880
mediaType:         db    0xf0
numFATsectors:     dw    9
sectorsPerTrack:   dw    18
numHeads:          dw    2
numHiddenSectors:  dd    0
numSectorsHuge:    dd    0
driveNum:          db    0
reserved:          db    0
signature:         db    0x29
volumeID:          dd    0x2d7e5a1a
volumeLabel:       db    "NO NAME    "
fileSysType:       db    "FAT12   "
boot:
mov ax, 0x2401
int 0x15 ; enable A20 bit
mov ax, 0x0003 ; change the video mode to 0x03
int 0x10
lgdt [gdt_pointer] ; load the gdt table
mov eax, cr0 
or eax, 0x1 ; set the protected mode bit on special CPU reg cr0
mov cr0, eax
jmp code_seg:main ; long jump to the code segment code_seg
gdt_start:
dq 0x0
gdt_code:
dw 0xFFFF
dw 0
db 0
db 0b10011010
db 0b11001111
db 0
gdt_data:
dw 0xFFFF
dw 0
db 0
db 0b10010010
db 0b11001111
db 0
gdt_end:
gdt_pointer:
dw gdt_end - gdt_start
dd gdt_start
code_seg equ gdt_code - gdt_start
data_seg equ gdt_data - gdt_start
bits 32
main:
mov ax, data_seg
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov ebp, 0x90000
mov esp, ebp
mov ebx, 0xb8000
mov al, '!'
mov ah, 0b00001111
mov word[ebx], ax
cli
jmp $
times 510 - ($-$$) db 0
dw 0xaa55

这段代码在虚拟机上运行良好,但它会导致几次屏幕闪烁,并在真正的机器上重新启动(我在两台电脑上测试过(。更改几行(删除"位32"、"或eax,0x1",并将"jmp-code_seg:main"替换为"jmp-main"(以使用16位模式而不是32位保护模式会使代码正常工作。但是,当我使用32位模式时,它会失败。为什么会这样?提前谢谢。

问题是您没有将ds初始化为零。您正在使用以下lgdt指令:

lgdt [gdt_pointer] ; load the gdt table

此内存访问隐式地使用默认段,对于没有bp的地址,该段为ds。您正在使用org 7C00h,因此希望ds为零。但是,当ROM-BIOS加载程序将控制权转移到您的加载程序时,在ds中保留任何可能的值是有效的。解决方案是在lgdt指令之前添加以下内容:

xor ax, ax
mov ds, ax

这使ax寄存器归零,然后使用它将ds初始化为零。

Michael Petch的Bootloader开发通用提示中也提供了此解决方案。

相关内容

最新更新