Weird behavior when writing to 0xB8000 / corrupted pointer

扶醉桌前 提交于 2021-01-28 08:12:12

问题


I'm currently developing an OS kernel from scratch. I want to use a function to write characters on the screen , using the 0xB8000 memory location.
the problem is the following :
I use :

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++ ;                                                                                                         

    }                                                                                                                    

}    

to print to the screen .

The function is called by :

void main(){                                                                                                                                                                       

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

}  

The OS boots correctly , but upon entering 32 bits PM and printing the message , I get this :

There is one additional character , at the beginning of the string , that I did not put.

When I dump the memory at 0xB8000 , I get this :

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 in Hex is "M" . It should be the first character in the string , but it isn't , for god knows what reason. Instead the first character is C3 , which is the garbage at the beginning of the string.

Nevertheless , printing these characters directly from the main() function works flawlessly , so my guess is that the pointer of the string got corrupted .

Do you guys have any idea of what's happening there ?

EDIT: Here's the Bootloader code :

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 is the in the GDT , gdt_data - gdt_start)

At 0x1000 I execute this code , which is the kernel entry

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

When dumping the memory after clear_screen() , I only get 0 , so this is working as intended.

I think it's really the string variable that contains this character , because when I do :

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++ ;                                                                                                       
}    

adding the "p++;" , the message prints without artifacts. So I don't think it's some garbage that was put specifically in 0xB8000. Offsetting the video memory so that the message prints in the middle of the screen for example , gives the same result : when I offset VIDEO_MEMORY by any value :

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++ ;                                                                                                       
}     

I get this :


回答1:


EDIT : okay , so I just figured where the problem was , but not really why. The problem is from the compilation and the linking ... I compiled previously for 64 bits elf , I just changed to 32 bits compiling/linking everywhere and the text prints correctly without artifacts.



来源:https://stackoverflow.com/questions/58633806/weird-behavior-when-writing-to-0xb8000-corrupted-pointer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!