写入0xB8000/损坏的指针时的行为异常 [英] Weird behavior when writing to 0xB8000 / corrupted pointer
问题描述
我目前正在从头开始开发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屋!