assembly GRUB在自定义操作系统开发中未切换到图形模式

a1o7rhls  于 2023-08-06  发布在  其他
关注(0)|答案(1)|浏览(76)

我正在开发一个定制的操作系统,并使用GRUB引导加载程序来加载我的内核。在我的开发过程中,我遇到了一个问题,我无法将显示模式从文本模式切换到图形模式。尽管将GRUB配置为在图形模式(1024 x768 x32)下启动,但系统在引导期间似乎仍处于文本模式。
下面提供了汇编 Bootstrap 和我尝试使用图形模式的内核部分:; bootloader.asm

[bits 32]

section .multiboot

align 4
dd 0x1BADB002            ; Multiboot magic number
dd 0x00                  ; Flags
dd -(0x1BADB002 + 0x00)  ; Checksum (must be such that all the dword sums to zero)

section .bootstrap_stack
align 16
stack_bottom: 
times 16384 db 0 ; Declare a stack of 16KB
stack_top:

section .text

extern kmain ; This should be in your kernel code
global start

start:

    mov esp, stack_top ; Set up the stack
    call kmain         ; Call the main function in the kernel
    cli                ; Disable interrupts
.hang:
    hlt                ; Halt the CPU
    jmp .hang          ; Infinite loop just in case

字符串
我的kernel.c文件看起来像://kernel.c

#define VIDEO_MEMORY 0xA0000

void print(char *str, int x, int y) {
    volatile char *video = (volatile char*)(0xB8000 + 2*x + 160*y);
    while (*str != 0) {
        *video = *str;
        video += 2;
        str++;
    }
}

#define VIDEO_MEMORY 0xA0000

void fill_screen(unsigned char color) {
    unsigned char* video_memory = (unsigned char*)VIDEO_MEMORY;
    int i;
    for (i = 0; i < 320 * 200; i++)
        video_memory[i] = color;
}

void draw_pixel(int x, int y, unsigned char color) {
    unsigned char* video_memory = (unsigned char*)VIDEO_MEMORY;
    int offset = y * 320 + x;
    video_memory[offset] = color;
}

void fillRect(int x, int y, int width, int height, unsigned char color) {
    unsigned char* video_memory = (unsigned char*)0xA0000;
    int i, j;
    for (i = y; i < y + height; i++) {
        for (j = x; j < x + width; j++) {
            draw_pixel(x+i,y+j, color);
        }
    }
}

void kmain() {
    print("hello", 0, 0);
    
        fill_screen(0x0F);     // Fill the screen with white color (0x0F)
        draw_pixel(160, 100, 0x0);   // Draw a black pixel at (160, 100)
    fillRect(5,10,20,20,0xFF);
    uint8_t* framebuffer = (uint8_t*)0xA0000; // Replace with your framebuffer address
    unsigned int bytes_per_pixel = 3; // Replace with your bytes per pixel
    unsigned int bytes_per_scanline = 1920; // Replace with your bytes per scanline
    unsigned int x = 10; // The x coordinate of the pixel
    unsigned int y = 10; // The y coordinate of the pixel

    uint8_t* pixel_address = framebuffer + y * bytes_per_scanline + x * bytes_per_pixel;
    pixel_address[0] = 0xFF; // Red
    pixel_address[1] = 0x00; // Green
    pixel_address[2] = 0x00; // Blue

}


下面是我的grub.cfg文件中的配置:

set default=0
set timeout=0

menuentry "My OS" {
    multiboot /boot/myos.bin
    set gfxpayload=1024x768x32
    insmod all_video
    boot
}


在我的内核中,我实现了一个打印函数,它将文本打印到屏幕上。我的期望是,如果系统成功地切换到图形模式,这个函数将失败,因为它是为文本模式设计的。但是,打印功能的工作方式就好像系统仍处于文本模式,这表明系统从未切换到图形模式。
我已经在几个虚拟机和物理机上尝试了这个设置,我一直遇到同样的问题。我目前使用的是GRUB 2.06版本。
尽管在GRUB配置中进行了指定,但为什么没有切换到图形模式,这让我很困惑。任何建议或指针将不胜感激!
请记住将注解“更多绘图函数”和“更多绘图代码”替换为您正在使用的实际绘图函数和代码。这将帮助其他人更准确地诊断您的问题。

gxwragnw

gxwragnw1#

您可以使用Multiboot2标头中的framebuffer标记来更改分辨率,而不是grub.cfg中的gfxpayload。
为此,在checksum之后添加以下内容:

dw 5
dw 0 ;instead of 0, you can specify your flags
dd 20
dd 1024 ;instead of 1024, you can specify your width
dd 768 ;instead of 768, you can specify your height
dd 32 ;instead of 32, you can specify your BPP

字符串
另外,不要忘记0xA0000的限制为64,000字节,并且您可以在32 BPP下绘制最大16,000像素。

相关问题