所以,我一直在尝试做一个简单的操作系统,进入模式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,导出内存等。
1条答案
按热度按时间lrpiutwd1#
我设法在真实的模式下初始化了视频模式,所以不需要保护模式内的vga代码。
对于任何有同样问题的人,这里是代码。
字符串
模式:https://web.archive.org/web/20030603170438/http://www.vesa.org/vbelink.html