Я делаю небольшую операционную систему, и я хочу разбираться с режимами видео (например, получать информацию о vesa, устанавливать режим видео), и в 32-битной версии это действительно сложно сделать, поэтому я решил вернуться в 16-битный режим. и я написал некоторый код, который переключается обратно на 16 бит из защищенного режима. Но когда я вызываю функцию, которую я написал в моем ядре, я не думаю, что она возвращается к моему ядру. Я также написал переключение на функцию 32-битного режима, чтобы вернуться к 32-битной, но ни одна из моих функций после этого не работает
Я попытался поместить много функций ret в функцию switch 16, чтобы проверить, вернется ли она к ядру. Я попытался поставить пиксель после того, как я переключился обратно на 32 бит с 16 бит. Но ни один из них не сработал, и я не получил никаких результатов
Мой переключатель на 16-битную функцию
[BITS 32]
global _switch16
_switch16:
cli
xor eax, eax
mov cr3, eax
lgdt [gdt_real_d]
jmp CODE_SEG:p16mode
ret
ivt_real:
dd 0x3FF
dd 0x0
gdt_real:
gdt_null : ; the mandatory null descriptor
dd 0x0 ; 'dd ' means define double word ( i.e. 4 bytes )
dd 0x0
gdt_code :
dw 0xffff ; Limit ( bits 0 -15)
dw 0x0 ; Base ( bits 0 -15)
db 0x0 ; Base ( bits 16 -23)
db 10011010b ; 1st flags , type flags
db 10001111b ; 2nd flags , Limit ( bits 16 -19)
db 0x0 ; Base ( bits 24 -31)
gdt_data :
dw 0xffff ; Limit ( bits 0 -15)
dw 0x0 ; Base ( bits 0 -15)
db 0x0 ; Base ( bits 16 -23)
db 10010010b ; 1st flags , type flags
db 10001111b ; 2nd flags , Limit ( bits 16 -19)
db 0x0 ; Base ( bits 24 -31)
gdt_end :
gdt_real_d :
dw gdt_end - gdt_real - 1
dd gdt_real
CODE_SEG equ gdt_code - gdt_real
DATA_SEG equ gdt_data - gdt_real
BITS 16
p16mode:
mov ax, DATA_SEG
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
and al,0xFE
mov cr0, eax
jmp 0:rmode
ret
rmode:
lidt [ivt_real]
mov ax, 0x9000
mov sp, ax
sti
ret
мой переключатель на 32-битную функцию
[BITS 16]
global _switch32
_switch32:
cli
lgdt [gdt_pmode_d]
mov eax , cr0
or eax , 0x1
mov cr0 , eax
jmp CODE_SEG:pmode
ret
gdt_pmode:
gdt_null : ; the mandatory null descriptor
dd 0x0 ; 'dd ' means define double word ( i.e. 4 bytes )
dd 0x0
gdt_code :
dw 0xffff ; Limit ( bits 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)
db 0x0 ; Base ( bits 24 -31)
gdt_data :
dw 0xffff ; Limit ( bits 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 ; Base ( bits 24 -31)
gdt_end :
gdt_pmode_d :
dw gdt_end - gdt_pmode - 1
dd gdt_pmode
CODE_SEG equ gdt_code - gdt_pmode
DATA_SEG equ gdt_data - gdt_pmode
BITS 32
pmode:
mov ax , DATA_SEG ; Now in PM , our old segments are meaningless ,
mov ds , ax
mov ss , ax
mov es , ax
mov fs , ax
mov gs , ax
mov ebp , 0x90000
mov esp , ebp
sti
ret
Мое ядро
#include <OS.h>
extern void switch16(void);
extern void switch32(void);
int kmain()
{
switch16();
switch32();
init_idt();
SetPITSpeed(100);
init_Cursor();
char* str = "Hello, world!\0";
printf(str,0xffffff,0x000000);
while(1);
}
Я компилирую и связываю с makefile
OS:
nasm -fbin Bootloader/bootload.asm -o Bin/bootload.bin
nasm -fbin Bootloader/diskpad.asm -o Bin/diskpad.bin
nasm Bootloader/A20Check.asm -f elf -o Bin/a20.o
nasm Bootloader/switch16.asm -f elf -o Bin/switch16.o
nasm Bootloader/switch32.asm -f elf -o Bin/switch32.o
gcc -mno-ms-bitfields -fno-PIC -m32 -ffreestanding -c Kernel/kernel.c -o Bin/kernel.o
nasm Kernel/kernel_entry.asm -f elf -o Bin/k_entry.o
ld -T link.ld -o Bin/kernel.tmp Bin/k_entry.o Bin/switch16.o Bin/switch32.o Bin/a20.o Bin/kernel.o
objcopy -O binary Bin/kernel.tmp Bin/kernel.bin
copy /b "Bin\bootload.bin" + "Bin\kernel.bin" + "Bin\diskpad.bin" /b "os-image.bin"
qemu-system-i386 -monitor stdio os-image.bin
Я уверен, что я могу переключиться на 16 бит, потому что я могу использовать прерывания в файле сборки (но не ядро). Я ожидаю, что код переключится на 16 бит, сделает некоторые прерывания BIOS, переключится обратно на 32, init_idt и показать некоторые признаки того, что это на самом деле работает. Но когда я запускаю приведенный выше код, я просто получаю пустой экран в режиме видео 1280x1024x24bpp (я переключился на него в моем загрузчике) Ни один пиксель не пишется, и printf не работает