Почему мой переключатель на 16-битную функцию, написанную на ассемблере, не возвращается к моему ядру? - PullRequest
0 голосов
/ 23 марта 2019

Я делаю небольшую операционную систему, и я хочу разбираться с режимами видео (например, получать информацию о 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 не работает

...