Я пишу простой загрузочный сектор сборки NASM.Код должен печатать текст на экране в режиме реального времени 16 бит, затем переключаться в защищенный режим 32 бита и печатать текст на экране.
Я использую QEMU в качестве эмулятора процессора, и он печатает текст из 16-битного режима, как и должно быть.Однако текст, который должен быть напечатан в 32-битном режиме, не печатается.
Я бы предположил, что это проблема с моим кодом, но я также запустил этот аналогичный код , с той же проблемой работы только в 16-битном режиме.
Не правильно ли я использую QEMU, или я что-то еще напутал?
Спасибо
Редактировать: добавлен код
boot_sector.asm
; Boot sector that enters 32 bit protected mode
[org 0x7c00]
mov bp, 0x9000 ; Set stack
mov sp, bp
mov bx, MSG_REAL_MODE
call print_string
call switch_to_pm ; We will never return to here
jmp $
%include "print_string.asm"
%include "gdt.asm"
%include "print_string_pm.asm"
%include "switch_to_pm.asm"
[bits 32]
;Where we arrive after switching to PM
BEGIN_PM:
mov ebx, MSG_PROTECTED_MODE
call print_string_pm ; 32 bit routine to print string
jmp $ ; Hang
; Global variables
MSG_REAL_MODE: db "Started in 16-bit real mode.", 0
MSG_PROTECTED_MODE: db "Successfully landed in 32-bit protected mode.", 0
; Boot sector padding
times 510-($-$$) db 0
dw 0xaa55
switch_to_pm.asm
[bits 16]
; Switch to protected mode
switch_to_pm:
mov bx, MSG_SWITCHING ; Log
call print_string
cli ; Clear interrupts
lgdt [gdt_descriptor] ; Load GDT
mov eax, cr0 ; Set the first bit of cr0 to move to protected mode, cr0 can't be set directly
or eax, 0x1 ; Set first bit only
mov cr0, eax
jmp CODE_SEG:init_pm ; Make far jump to to 32 bit code. Forces CPU to clear cache
[bits 32]
; Initialize registers and the stack once in PM
init_pm:
mov ax, DATA_SEG ; Now in PM, our old segments are meaningless
mov ds, ax ; so we point our segment registers to the data selector defined GDT
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ebp, 0x90000 ; Move stack
mov esp, ebp
call BEGIN_PM ; Call 32 bit PM code
; Global variables
MSG_SWITCHING: db "Switching to 32-bit protected mode...", 0
gdt.asm
gdt_start:
gdt_null: ; The mandatory null descriptor
dd 0x0 ; dd = define double word (4 bytes)
dd 0x0
gdt_code: ; Code segment descriptor
dw 0xffff ; Limit (bites 0-15)
dw 0x0 ; Base (bits 0-15)
db 0x0 ; Base (bits 16-23)
db 10011010b ; 1st flags, type flags
db 11001111b ; 2nd flags, limit (bits 16-19)
gdt_data:
dw 0xffff ; Limit (bites 0-15)
dw 0x0 ; Base (bits 0-15)
db 0x0 ; Base (bits 16-23)
db 10010010b ; 1st flags, type flags
db 11001111b ; 2nd flags, limit (bits 16-19)
db 0x0
gdt_end: ; necessary so assembler can calculate gdt size below
gdt_descriptor:
dw gdt_end - gdt_start - 1 ; GDT size
dd gdt_start ; Start adress of GDT
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start
print_string_pm.asm
[bits 32]
VIDEO_MEMORY equ 0xb8000
WHITE_ON_BLACK equ 0x0f
print_string_pm:
pusha
mov edx, VIDEO_MEMORY
print_str_pm_loop:
mov al, [ebx]
mov ah, WHITE_ON_BLACK
cmp al, 0
je print_str_pm_return
mov [edx], ax
add ebx, 1
add edx, 2
jmp print_str_pm_loop
print_str_pm_return:
popa
ret
print_string.asm
print_string:
pusha
mov ah, 0x0e
_print_str_loop:
mov al, [bx]
cmp al, 0
je _print_str_return
int 0x10
inc bx
jmp _print_str_loop
_print_str_return:
popa
ret
Команды: Для сборки:
nasm -f bin boot_sector.asm -o boot_sector.bin
Qemu:
qemu-system-x86_64 boot_sector.bin --nographic