C语言 osdev -保护模式下的VGA初始化异常

ekqde3dh  于 2024-01-06  发布在  其他
关注(0)|答案(1)|浏览(130)

所以,我一直在尝试做一个简单的操作系统,进入模式13 h(使用我以前使用的代码,应该在保护模式下工作(它至少在我以前的操作系统上使用grub作为 Bootstrap )
代码发布在下面。
当我尝试使用这个新代码时,我得到了非常非常奇怪的输出。向屏幕写入像素不起作用,但屏幕分辨率的变化确实表明启动了一些视频模式。
视频模式在Y轴上大约为640 px,在X轴上大约为1940 px
下面是用于初始化c代码的asm代码,以防出现问题。
ASM加载程序:

[org 0x7C00]
bits 16
_start:
    ;segment registers
    mov ax, 0x0000
    mov ss, ax
    mov sp, 0x7C00
    mov ax, 0x07E0
    mov ds, ax
    
    ;enter protected mode
    cli
    lgdt [gdtr]
    mov eax, cr0
    or eax, 1 
    mov cr0, eax
    jmp main
gdt_start:
    dq 0x0000000000000000
    dq 0x00CF9A000000FFFF
    dq 0x00CF92000000FFFF
gdt_end:
gdtr:
    dw gdt_end - gdt_start - 1
    dd gdt_start
main:
    ;Segment reload 2
    mov ax, DATA_SEG
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax

字符串
C程序(最简单的例子):

#include <stdint.h>
unsigned char g_320x200x256[] =
{
/* MISC */
    0x63,
/* SEQ */
    0x03, 0x01, 0x0F, 0x00, 0x0E,
/* CRTC */
    0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F,
    0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x9C, 0x0E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3,
    0xFF,
/* GC */
    0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
    0xFF,
/* AC */
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
    0x41, 0x00, 0x0F, 0x00, 0x00
};
#define VGA_AC_INDEX        0x3C0
#define VGA_AC_WRITE        0x3C0
#define VGA_AC_READ         0x3C1
#define VGA_INSTAT_READ     0x3DA
#define VGA_MISC_WRITE      0x3C2
#define VGA_MISC_READ       0x3CC
#define VGA_ADDRESS 0xA0000
/*          COLOR emulation     MONO emulation */
#define VGA_CRTC_INDEX      0x3D4       /* 0x3B4 */
#define VGA_CRTC_DATA       0x3D5       /* 0x3B5 */
#define VGA_GC_INDEX        0x3CE
#define VGA_GC_DATA         0x3CF
#define VGA_SEQ_INDEX       0x3C4
#define VGA_SEQ_DATA        0x3C5

#define VGA_NUM_AC_REGS     21
#define VGA_NUM_CRTC_REGS   25
#define VGA_NUM_GC_REGS     9
#define VGA_NUM_SEQ_REGS    5

uint8_t inb(uint16_t port) {
    uint8_t value;
    asm volatile ("inb %1, %0" : "=a"(value) : "Nd"(port));
    return value;
}
void outb(uint16_t port, uint8_t value) {
    asm volatile ("outb %0, %1" : : "a"(value), "Nd"(port));
}
int main(){
    unsigned char* regs = g_320x200x256;
    unsigned i;

   ; vga mode driver (originally from osdev wiki)

/* write MISCELLANEOUS reg */
    outb(VGA_MISC_WRITE, *regs);
    regs++;
/* write SEQUENCER regs */
    for(i = 0; i < VGA_NUM_SEQ_REGS; i++)
    {
        outb(VGA_SEQ_INDEX, i);
        outb(VGA_SEQ_DATA, *regs);
        regs++;
    }
/* unlock CRTC registers */
    outb(VGA_CRTC_INDEX, 0x03);
    outb(VGA_CRTC_DATA, inb(VGA_CRTC_DATA) | 0x80);
    outb(VGA_CRTC_INDEX, 0x11);
    outb(VGA_CRTC_DATA, inb(VGA_CRTC_DATA) & ~0x80);
/* make sure they remain unlocked */
    regs[0x03] |= 0x80;
    regs[0x11] &= ~0x80;
/* write CRTC regs */
    for(i = 0; i < VGA_NUM_CRTC_REGS; i++)
    {
        outb(VGA_CRTC_INDEX, i);
        outb(VGA_CRTC_DATA, *regs);
        regs++;
    }
/* write GRAPHICS CONTROLLER regs */
    for(i = 0; i < VGA_NUM_GC_REGS; i++)
    {
        outb(VGA_GC_INDEX, i);
        outb(VGA_GC_DATA, *regs);
        regs++;
    }
/* write ATTRIBUTE CONTROLLER regs */
    for(i = 0; i < VGA_NUM_AC_REGS; i++)
    {
        (void)inb(VGA_INSTAT_READ);
        outb(VGA_AC_INDEX, i);
        outb(VGA_AC_WRITE, *regs);
        regs++;
    }
/* lock 16-color palette and unblank display */
    (void)inb(VGA_INSTAT_READ);
    outb(VGA_AC_INDEX, 0x20);
    unsigned char *VGA = (unsigned char*) VGA_ADDRESS;
    VGA[0] = 0;
    VGA[1] = 1;
    VGA[2] = 2;
    ;Infinite loop at end
    while(1);
}


现在,我将在asm引导加载程序和0x 55 AA之后的第511和第512字节复制编译后的二进制代码
重现步骤:
nasm -f bin kernel.asm编译引导加载程序
i686-elf-gcc -nostdlib -ffreestanding -O2 -Wall -Wextra -m32 -c vgacode.c -o kern_c.o编译c文件(i386-gcc也可以)
objcopy -O binary kern_c.o kernel.o从elf 32转换为bin
然后,您可以使用cat(cat kenrnel kernel.o > file2.bin)复制代码,并使用以下命令进行仿真:
qemu-system-x86_64 -fda file2.bin
我试着重新检查代码,在各种模式下使用qemu,导出内存等。

lrpiutwd

lrpiutwd1#

我设法在真实的模式下初始化了视频模式,所以不需要保护模式内的vga代码。
对于任何有同样问题的人,这里是代码。

mov ax, 0x4F02
    mov bx, 0x11B
    int 0x10

    or

    mov ah, 0
    mov al, 13h
    int 0x10

字符串
模式:https://web.archive.org/web/20030603170438/http://www.vesa.org/vbelink.html

相关问题