写入0xB8000/损坏的指针时的行为异常 [英] Weird behavior when writing to 0xB8000 / corrupted pointer

查看:127
本文介绍了写入0xB8000/损坏的指针时的行为异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在从头开始开发OS内核. 我想使用一个函数在屏幕上使用0xB8000内存位置写入字符.
问题如下:
我使用:

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

    }                                                                                                                    

}    

打印到屏幕上.

该函数由调用:

void main(){                                                                                                                                                                       

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

}  

操作系统正常启动,但是在输入32位PM并打印消息后,我得到了:

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.

当我将内存转储到0xB8000时,我得到了:

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是"M".它应该是字符串中的第一个字符,但不是,因为上帝知道原因. 相反,第一个字符是C3,它是字符串开头的垃圾.

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.

尽管如此,直接从main()函数打印这些字符还是可以正常工作,所以我的猜测是字符串的指针已损坏.

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 ?

这是Bootloader代码:

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是GDT中的,gdt_data-gdt_start)

(DATA_SEG is the in the GDT , gdt_data - gdt_start)

在0x1000,我执行此代码,这是内核条目

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

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

在clear_screen()之后转储内存时,我只能得到0,所以这按预期工作.

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

添加"p ++;" ,该消息将打印而没有伪像. 因此,我认为这不是专门放在0xB8000中的垃圾. 偏移视频内存,以便消息显示在屏幕中间,例如,得到相同的结果: 当我将VIDEO_MEMORY偏移任何值时:

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

我明白了:

推荐答案

好的,所以我只是想知道问题出在哪里,但并不是真正的原因. 问题来自于编译和链接... 我以前是为64位elf编译的,我只是更改为32位,可以在各处编译/链接,并且文本可以正确打印而没有伪像.

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.

这篇关于写入0xB8000/损坏的指针时的行为异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆