Странное поведение при записи в 0xB8000 / поврежденный указатель - PullRequest
1 голос
/ 31 октября 2019

Я сейчас занимаюсь разработкой ядра ОС с нуля. Я хочу использовать функцию для записи символов на экране, используя ячейку памяти 0xB8000.
Проблема заключается в следующем:
Я использую:

void video_write(const unsigned char *string , char color ){                                                                 
    unsigned char *p = (unsigned char*) string ;                                                                         
    char *c = (char*) (VIDEO_MEMORY ); //VIDEO_MEMORY is 0XB8000                                                                                                                                                                                           
    while(*p != '\0')                                                                                                    
    {                                                                                                                    
            *c = p[0] ;                                                                                                 
            c++ ;                                                                                                       
            *c = color ;                                                                                                
            c++ ;                                                                                                       
            p++ ;                                                                                                       
    }                                                                                                                   


} 
void clear_screen(){                                                                                                                                                               
    char *c = (char*) VIDEO_MEMORY ;                                                                                                                                                                     
    int i = 0 ;                                                                                                                                  
    for(i ; i < 4000 ; i++){                                                                                                                                                       
            *c='\0' ;                                                                                                    
            c++ ;                                                                                                         

    }                                                                                                                    

}    

для печати на экране.

Функция вызывается:

void main(){                                                                                                                                                                       

    clear_screen() ;                                                                                                                             
    video_write("Message\0"  ,  0x0E);                                                                                                                                             

}  

Операционная система загружается правильно, но после ввода 32-битного PM и печати сообщения я получаю следующее:

enter image description here

В начале строки есть еще один символ, который я не поставил.

Когда я выкидываю память в 0xB8000, я получаю это:

00000000: c30e 4d0e 650e 730e 730e 610e 670e 650e  ..M.e.s.s.a.g.e.
00000010: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000020: 0000 0000 0000 0000 0000 0000 0000 0000  ................

4D в шестнадцатеричном - это "M". Это должен быть первый символ в строке, но это не так, потому что бог знает, по какой причине. Вместо этого первым символом является C3, который является мусором в начале строки.

Тем не менее, печать этих символов непосредственно из функции main () работает безупречно, поэтому я предполагаю, что указатель на строку получилиспорчен.

Ребята, вы хоть представляете, что там происходит?

РЕДАКТИРОВАТЬ: Вот код загрузчика:

ifndef BOOT_ASM
%define BOOT_ASM
[org 0x7C00]
KERNEL_OFFSET equ 0x1000
[bits 16]

    mov [BOOT_DRIVE] , dl
    mov BP , 0x9000
    mov SP , BP

    call load_kernel
    call switch_pm


    %include "print.asm"
    %include "hexprint.asm"
    %include "disk_io.asm" 
    %include "GDT.asm" 


    load_kernel :
        mov SI , KERNEL_MSG
        call print_string
        mov BX , KERNEL_OFFSET
        mov DH , 15 
        mov DL , [BOOT_DRIVE]
        call disk_load
        ret

    switch_pm:
        cli
        lgdt [gdt_descriptor]
        mov EAX , CR0
        or EAX , 1
        mov CR0 , EAX
        jmp CODE_SEG:PM_init

    [bits 32]
    PM_init:
        mov AX , DATA_SEG
        mov DS , AX
        mov SS , AX
        mov ES , AX
        mov FS , AX
        mov GS , AX

        mov EBP , 0x90000
        mov ESP , EBP

        call BEGIN_PM
        jmp $

    BEGIN_PM : 
        call KERNEL_OFFSET
        ret



    BOOT_DRIVE: db 0
    RM_MSG db "SAHARA OS , Real mode" , 0x0
    PM_MSG db "SAHARA OS , Protected mode" , 0x0
    KERNEL_MSG db "SaharaOS : Oasis kernel " , 0x0A , 0x0D , 0x0

    times 510 - ($-$$) db 0 
    dw 0xaa55



    %endif 

(DATA_SEG - это GDT, gdt_data- gdt_start)

В 0x1000 я выполняю этот код, который является записью ядра

[bits 32]
[extern main]
    call main
    jmp $

При сбросе памяти после clear_screen () я получаю только 0, так что это работает, как и предполагалось.

Я думаю, что это действительно строковая переменная, которая содержит этот символ, потому что, когда я делаю:

void video_write(const unsigned char *string , char color ){                                                                 
unsigned char *p = (unsigned char*) string ;  
p++ ;                                                                        
char *c = (char*) (VIDEO_MEMORY ); //VIDEO_MEMORY is 0XB8000                                                                                                                                                                                           
while(*p != '\0')                                                                                                    
{                                                                                                                    
        *c = *p ;                                                                                                 
        c++ ;                                                                                                       
        *c = color ;                                                                                                
        c++ ;                                                                                                       
        p++ ;                                                                                                       
}    

с добавлением "p ++;"сообщение печатается без артефактов. Так что я не думаю, что это какой-то мусор, который был помещен специально в 0xB8000. Смещение видеопамяти, чтобы сообщение печаталось, например, в середине экрана, дает тот же результат: когда я смещаю VIDEO_MEMORY на любое значение:

void video_write(const unsigned char *string , char color ){                                                                 
unsigned char *p = (unsigned char*) string ;                                                                         
char *c = (char*) (VIDEO_MEMORY + 1980 ); //VIDEO_MEMORY is 0XB8000                                                                                                                                                                                           
while(*p != '\0')                                                                                                    
{                                                                                                                    
        *c = p[0] ;                                                                                                 
        c++ ;                                                                                                       
        *c = color ;                                                                                                
        c++ ;                                                                                                       
        p++ ;                                                                                                       
}     

, я получаю это: enter image description here

1 Ответ

1 голос
/ 31 октября 2019

РЕДАКТИРОВАТЬ: хорошо, так что я просто понял, где проблема, но не совсем, почему. Проблема заключается в компиляции и компоновке ... Ранее я компилировал для 64-битного эльфа, я просто перешел на 32-битную компиляцию / компоновку везде, и текст печатается правильно без артефактов.

...