c语言 - 如何修复操作系统的 VBE 实现?



我正在缓慢但肯定地开发一个小型操作系统,我终于认为我有一些代码应该(理论上)输出到 VESA VBE。但是,我在尝试编译时遇到一系列错误。我确定我的代码有问题,尽管我不知道是什么。我看到了错误,但我不知道如何修复它们。有关更多相关信息,您可以查看我的混乱代码的一些来源:

  1. 我从这里得到了VBE_modeInfo结构
  2. 我从上一个问题中得到了u32 modeInfoPointer = asm volatile ("eax");u32 physical_address = modeInfo.PhysBasePtr + y * modeInfo.LinBytesPerScanLine + x * bytesPerPixel;和很多汇编代码

这是我的一长串错误,如果有人好奇的话。我不认为boot.asm是问题所在,考虑到我没有提到它的错误。在这里,我将把kernel.cpp和我的GitHub留给其余的代码:

内核.cpp:

typedef unsigned char uint8_t;
typedef unsigned char u8;
typedef unsigned short uint16_t;
typedef unsigned int u32;
typedef u32 size_t;
typedef unsigned long phys_bytes;
#define SCREEN_WIDTH (int)(modeInfo.XResolution)
#define SCREEN_HEIGHT (int)(modeInfo.YResolution)
#define BPP 32
#define SCREEN_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT)
#define FPS 30
#define PIT_HERTZ 1193131.666
#define CLOCK_HIT (int)(PIT_HERTZ/FPS)
#define KEY_LEFT 0x4B
#define KEY_UP 0x48
#define KEY_RIGHT 0x4D
#define KEY_DOWN 0x50
typedef struct VBE_modeInfo{
/*  Mandatory information for all VBE revisions */
uint16_t ModeAttributes;   
uint8_t WinAAttributes;    
uint8_t WinBAttributes;    
uint16_t WinGranularity;   
uint16_t WinSize;          
uint16_t WinASegment;      
uint16_t WinBSegment;      
phys_bytes WinFuncPtr;     
uint16_t BytesPerScanLine; 
/* Mandatory information for VBE 1.2 and above */
uint16_t XResolution;       
uint16_t YResolution;       
uint8_t XCharSize;          
uint8_t YCharSize;          
uint8_t NumberOfPlanes;     
uint8_t BitsPerPixel;       
uint8_t NumberOfBanks;      
uint8_t MemoryModel;        
uint8_t BankSize;           
uint8_t NumberOfImagePages; 
uint8_t Reserved1;          
/* Direct Color fields (required for direct/6 and YUV/7 memory models) */
uint8_t RedMaskSize;         /* size of direct color red mask in bits */
uint8_t RedFieldPosition;    /* bit position of lsb of red mask */
uint8_t GreenMaskSize;       /* size of direct color green mask in bits */
uint8_t GreenFieldPosition;  /* bit position of lsb of green mask */
uint8_t BlueMaskSize;        /* size of direct color blue mask in bits */
uint8_t BlueFieldPosition;   /* bit position of lsb of blue mask */
uint8_t RsvdMaskSize;        /* size of direct color reserved mask in bits */
uint8_t RsvdFieldPosition;   /* bit position of lsb of reserved mask */
uint8_t DirectColorModeInfo; /* direct color mode attributes */
/* Mandatory information for VBE 2.0 and above */
phys_bytes PhysBasePtr; 
uint8_t Reserved2[4];   
uint8_t Reserved3[2];   
/* Mandatory information for VBE 3.0 and above */
uint16_t LinBytesPerScanLine;  /* bytes per scan line for linear modes */
uint8_t BnkNumberOfImagePages; /* number of images for banked modes */
uint8_t LinNumberOfImagePages; /* number of images for linear modes */
uint8_t LinRedMaskSize;        /* size of direct color red mask (linear modes) */
uint8_t LinRedFieldPosition;   /* bit position of lsb of red mask (linear modes) */
uint8_t LinGreenMaskSize;      /* size of direct color green mask (linear modes) */
uint8_t LinGreenFieldPosition; /* bit position of lsb of green mask (linear  modes) */
uint8_t LinBlueMaskSize;       /* size of direct color blue mask (linear modes) */
uint8_t LinBlueFieldPosition;  /* bit position of lsb of blue mask (linear modes ) */
uint8_t LinRsvdMaskSize;       /* size of direct color reserved mask (linear modes) */
uint8_t LinRsvdFieldPosition;  /* bit position of lsb of reserved mask (linear modes) */
u32 MaxPixelClock;        /* maximum pixel clock (in Hz) for graphics mode */
uint8_t Reserved4[190];        /* remainder of ModeInfoBlock */
} VBE_modeInfo;
u32 modeInfoPointer = asm volatile ("eax");
#define modeInfo (struct VBE_modeInfo *)modeInfoPointer
static u32 *BUFFER = (u32 *) modeInfo.PhysBasePtr;
// double buffers
u32 _sbuffers[2][SCREEN_SIZE];
u32 _sback = 0;
#define CURRENT (_sbuffers[_sback])
#define SWAP() (_sback = 1 - _sback)
#define screen_buffer() (_sbuffers[_sback])
static inline void outb(uint16_t port, uint8_t val)
{
asm volatile ( "outb %0, %1" : : "a"(val), "Nd"(port) );
}
#define bytesPerPixel ((modeInfo->BitsPerPixel + 7) / 8)
void screen_set(u32 color,int x,int y) {
u32 physical_address = modeInfo.PhysBasePtr + y * modeInfo.LinBytesPerScanLine + x * bytesPerPixel;
_sbuffers[_sback][physical_address]=color;
}
static inline uint8_t inb(uint16_t port)
{
uint8_t ret;
asm volatile ( "inb %1, %0"
: "=a"(ret)
: "Nd"(port) );
return ret;
}
const unsigned char font[128-32][8] = {
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0020 (space)
/*deleted to help with length of code...*/
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}    // U+007F
};
static inline void *memcpy(void *dst, const void *src, size_t n)
{
u8 *d = (u8*)dst;
const u8 *s = (const u8*)src;
while (n-- > 0) {
*d++ = *s++;
}
return d;
}
void screen_swap() {
memcpy(BUFFER, CURRENT, SCREEN_SIZE);
SWAP();
}
unsigned read_pit(void) {
unsigned count = 0;

// al = channel in bits 6 and 7, remaining bits clear
outb(0x43,0b0000000);

count = inb(0x40);          // Low byte
count |= inb(0x40)<<8;      // High byte

return count;
}

void draw_char(char c, int x, int y, u32 color)
{
const unsigned char *glyph = font[(int)c-32];

for(int cy=0;cy<8;cy++){
for(int cx=0;cx<8;cx++){
if(((int)glyph[cy]&(1<<cx))==(1<<cx)){
screen_set(color,x+cx,y+cy);
}
} 
}
}
void draw_string(const char * s, int x, int y, u32 color) {
int i = 0;
while(s[i] != false) {
draw_char(s[i],x+(i*8),y,color);
i++;
}
}
void draw_rect(int pos_x, int pos_y, int w, int h, u32 color) {
for(int y = 0; y<h; y++) {
for(int x = 0; x<w; x++) {
screen_set(color,x+pos_x,y+pos_y);
}
}
}
static void render(int c0, int c1) {
//draw_rect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,0);
//draw_string("Hello, reader. This is written text.", 100, 180, 16777215);
//draw_string("If this is displayed, my code works.", 100+c0, 100+c1, 16777215);
}
extern "C" void main(){

int clock = 0;
int incC1 = 0;
int incC0 = 0;
while(true) {
uint16_t scancode = (uint16_t) inb(0x60);
clock++;
if(read_pit()!= 0 && clock == CLOCK_HIT) {
if(scancode == KEY_LEFT) {
incC0--;
}else if(scancode == KEY_RIGHT) {
incC0++;
}
if(scancode == KEY_DOWN) {
incC1++;
}else if(scancode == KEY_UP) {
incC1--;
}
clock = 0;
render(incC0,incC1);
screen_swap();
}
}
return;
}

编辑:我将在此处添加其余的相关代码。我的GitHub上的Shell文件和完整src

错误:

kernel.cpp:85:23: error: expected primary-expression before 'asm'
85 | u32 modeInfoPointer = asm volatile ("eax");
|                       ^~~
kernel.cpp:88:39: error: request for member 'PhysBasePtr' in 'modeInfoPointer', which is of non-class type 'u32' {aka 'unsigned int'}
88 | static u32 *BUFFER = (u32 *) modeInfo.PhysBasePtr;
|                                       ^~~~~~~~~~~
kernel.cpp:17:37: error: request for member 'XResolution' in 'modeInfoPointer', which is of non-class type 'u32' {aka 'unsigned int'}
17 | #define SCREEN_WIDTH (int)(modeInfo.XResolution)
|                                     ^~~~~~~~~~~
kernel.cpp:20:22: note: in expansion of macro 'SCREEN_WIDTH'
20 | #define SCREEN_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT)
|                      ^~~~~~~~~~~~
kernel.cpp:91:18: note: in expansion of macro 'SCREEN_SIZE'
91 | u32 _sbuffers[2][SCREEN_SIZE];
|                  ^~~~~~~~~~~
kernel.cpp:18:38: error: request for member 'YResolution' in 'modeInfoPointer', which is of non-class type 'u32' {aka 'unsigned int'}
18 | #define SCREEN_HEIGHT (int)(modeInfo.YResolution)
|                                      ^~~~~~~~~~~
kernel.cpp:20:37: note: in expansion of macro 'SCREEN_HEIGHT'
20 | #define SCREEN_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT)
|                                     ^~~~~~~~~~~~~
kernel.cpp:91:18: note: in expansion of macro 'SCREEN_SIZE'
91 | u32 _sbuffers[2][SCREEN_SIZE];
|                  ^~~~~~~~~~~
kernel.cpp: In function 'void screen_set(u32, int, int)':
kernel.cpp:107:37: error: request for member 'PhysBasePtr' in 'modeInfoPointer', which is of non-class type 'u32' {aka
unsigned int'}
107 |     u32 physical_address = modeInfo.PhysBasePtr + y * modeInfo.LinBytesPerScanLine + x * bytesPerPixel;
|                                     ^~~~~~~~~~~
kernel.cpp:107:64: error: request for member 'LinBytesPerScanLine' in 'modeInfoPointer', which is of non-class type 'u3
' {aka 'unsigned int'}
107 |     u32 physical_address = modeInfo.PhysBasePtr + y * modeInfo.LinBytesPerScanLine + x * bytesPerPixel;
|                                                                ^~~~~~~~~~~~~~~~~~~
kernel.cpp:104:33: error: base operand of '->' is not a pointer
104 | #define bytesPerPixel ((modeInfo->BitsPerPixel + 7) / 8)
|                                 ^~
kernel.cpp:107:90: note: in expansion of macro 'bytesPerPixel'
107 |     u32 physical_address = modeInfo.PhysBasePtr + y * modeInfo.LinBytesPerScanLine + x * bytesPerPixel;
|                                                                                          ^~~~~~~~~~~~~
kernel.cpp:108:5: error: '_sbuffers' was not declared in this scope
108 |     _sbuffers[_sback][physical_address]=color;
|     ^~~~~~~~~
kernel.cpp: In function 'void screen_swap()':
kernel.cpp:94:18: error: '_sbuffers' was not declared in this scope
94 | #define CURRENT (_sbuffers[_sback])
|                  ^~~~~~~~~
kernel.cpp:232:20: note: in expansion of macro 'CURRENT'
232 |     memcpy(BUFFER, CURRENT, SCREEN_SIZE);
|                    ^~~~~~~
kernel.cpp:17:37: error: request for member 'XResolution' in 'modeInfoPointer', which is of non-class type 'u32' {aka 'unsigned int'}
17 | #define SCREEN_WIDTH (int)(modeInfo.XResolution)
|                                     ^~~~~~~~~~~
kernel.cpp:20:22: note: in expansion of macro 'SCREEN_WIDTH'
20 | #define SCREEN_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT)
|                      ^~~~~~~~~~~~
kernel.cpp:232:29: note: in expansion of macro 'SCREEN_SIZE'
232 |     memcpy(BUFFER, CURRENT, SCREEN_SIZE);
|                             ^~~~~~~~~~~
kernel.cpp:18:38: error: request for member 'YResolution' in 'modeInfoPointer', which is of non-class type 'u32' {aka 'unsigned int'}
18 | #define SCREEN_HEIGHT (int)(modeInfo.YResolution)
|                                      ^~~~~~~~~~~
kernel.cpp:20:37: note: in expansion of macro 'SCREEN_HEIGHT'
20 | #define SCREEN_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT)
|                                     ^~~~~~~~~~~~~
kernel.cpp:232:29: note: in expansion of macro 'SCREEN_SIZE'
232 |     memcpy(BUFFER, CURRENT, SCREEN_SIZE);
|                             ^~~~~~~~~~~

引导.asm:

[org 0x7c00]                        
KERNEL_LOCATION equ 0x1000

xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x8000
mov [BOOT_DISK], dl
;Get video mode info
mov ax, 4f01h
mov cx, 105h
mov di, modeInfo 
int 10h
mov eax, modeInfo
mov bx, KERNEL_LOCATION
mov dh, 32
mov ah, 0x02
mov al, dh 
mov ch, 0x00
mov dh, 0x00
mov cl, 0x02
mov dl, [BOOT_DISK]
int 0x13

mov ax, 0x4F02   ; set VBE mode
mov bx, 0x4118   ; VBE mode number
int 0x10         ; call VBE BIOS
cmp ax, 0x004F   ; test for error
jne error
CODE_SEG equ GDT_code - GDT_start
DATA_SEG equ GDT_data - GDT_start
cli
lgdt [GDT_descriptor]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp CODE_SEG:start_protected_mode
jmp $
modeInfo    TIMES 256 db 0
error:
stc
ret
BOOT_DISK: db 0
GDT_start:
GDT_null:
dd 0x0
dd 0x0
GDT_code:
dw 0xffff
dw 0x0
db 0x0
db 0b10011010
db 0b11001111
db 0x0
GDT_data:
dw 0xffff
dw 0x0
db 0x0
db 0b10010010
db 0b11001111
db 0x0
GDT_end:
GDT_descriptor:
dw GDT_end - GDT_start - 1
dd GDT_start

[bits 32]
start_protected_mode:
mov ax, DATA_SEG
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esp, 0x00090000     ; 32 bit stack base pointer
mov ebp, esp            ; Only if you need this!
jmp KERNEL_LOCATION


times 510-($-$$) db 0              
dw 0xaa55

好的,根据所有顶级评论...

我们希望从eax设置modeInfoPointer,因为它包含 VBE 指针。

boot.asm,它从int 0x10得到这个。但是,我们必须把它移到某个地方。当我们跳到start_protected_mode并执行以下操作时,它会被破坏:

mov ax, DATA_SEG

所以,我们需要(作为它的第一个指令):

mov edi, eax ; save VBE pointer

然后,就在jmp KERNEL_LOCATION之前,我们需要:

push edi ; save as first argument to main

此外,我们想要call而不是jmp

然后,在kernel.cpp中,我们需要:

struct VBE_modeInfo *modeInfoPointer;
extern "C" void main(struct VBE_modeInfo *vbe)
{
modeInfoPointer = vbe;

还有其他调整。使用modeInfo不符合modeInfo.modeInfo->

我已经尽我所能纠正了编译错误。几乎可以肯定它仍然坏了,但应该让你走得更远。

它应该解决我们希望modeInfoPointer指向 VBE 块 [AFAICT] 的问题。


在下面的代码中,我使用了cpp条件来表示旧代码与新代码:

#if 0
// old code
#else
// new code
#endif
#if 1
// new code
#endif

注意:这可以通过运行文件来清理unifdef -k


这是针对 github 存储库的补丁:

diff --git a/src/OS.bin b/src/OS.bin
deleted file mode 100644
index 2957814..0000000
Binary files a/src/OS.bin and /dev/null differ
diff --git a/src/boot.asm b/src/boot.asm
index 0ee58af..a41730a 100644
--- a/src/boot.asm
+++ b/src/boot.asm
@@ -83,6 +83,7 @@ GDT_descriptor:
[bits 32]
start_protected_mode:
+   mov edi, eax    ; save VBE pointer
mov ax, DATA_SEG
mov ds, ax
mov es, ax
@@ -92,9 +93,8 @@ start_protected_mode:
mov esp, 0x00090000     ; 32 bit stack base pointer
mov ebp, esp            ; Only if you need this!
-    jmp KERNEL_LOCATION
-
-
+   push edi                ; save as first argument to main
+    call KERNEL_LOCATION
times 510-($-$$) db 0
dw 0xaa55
diff --git a/src/kernel.cpp b/src/kernel.cpp
index 79ef409..49282bb 100644
--- a/src/kernel.cpp
+++ b/src/kernel.cpp
@@ -14,8 +14,13 @@ typedef unsigned short uint16_t;
typedef unsigned int u32;
typedef u32 size_t;
typedef unsigned long phys_bytes;
+#if 0
#define SCREEN_WIDTH (int)(modeInfo.XResolution)
#define SCREEN_HEIGHT (int)(modeInfo.YResolution)
+#else
+#define SCREEN_WIDTH (int)(modeInfo->XResolution)
+#define SCREEN_HEIGHT (int)(modeInfo->YResolution)
+#endif
#define BPP 32
#define SCREEN_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT)
#define FPS 30
@@ -82,16 +87,28 @@ u32 MaxPixelClock;        /* maximum pixel clock (in Hz) for graphics mode */
uint8_t Reserved4[190];        /* remainder of ModeInfoBlock */
} VBE_modeInfo;
+#if 0
u32 modeInfoPointer = asm volatile ("eax");
#define modeInfo (struct VBE_modeInfo *)modeInfoPointer
+#else
+struct VBE_modeInfo *modeInfoPointer;
+#define modeInfo modeInfoPointer
+#endif
-static u32 *BUFFER = (u32 *) modeInfo.PhysBasePtr;
+static u32 *BUFFER = (u32 *) modeInfo->PhysBasePtr;
// double buffers
+#if 0
u32 _sbuffers[2][SCREEN_SIZE];
+#else
+u32 *_sbuffers;
+#endif
u32 _sback = 0;
-#define CURRENT (_sbuffers[_sback])
+#define SBUF(_y,_x) 
+   _sbuffers[((_y) * SCREEN_SIZE) + _x]
+
+#define CURRENT &SBUF(0,0)
#define SWAP() (_sback = 1 - _sback)
#define screen_buffer() (_sbuffers[_sback])
@@ -103,9 +120,26 @@ static inline void outb(uint16_t port, uint8_t val)
#define bytesPerPixel ((modeInfo->BitsPerPixel + 7) / 8)
+#ifndef NULL
+//#define NULL nullptr
+#include <cstddef>
+#include <cstdlib>
+#endif
+
void screen_set(u32 color,int x,int y) {
+#if 0
u32 physical_address = modeInfo.PhysBasePtr + y * modeInfo.LinBytesPerScanLine + x * bytesPerPixel;
+#else
+    u32 physical_address = modeInfo->PhysBasePtr + y * modeInfo->LinBytesPerScanLine + x * bytesPerPixel;
+#endif
+#if 0
_sbuffers[_sback][physical_address]=color;
+#else
+   if (_sbuffers == NULL)
+       _sbuffers = (u32 *) malloc(sizeof(u32) * 2 * SCREEN_SIZE);
+
+    SBUF(_sback,physical_address)=color;
+#endif
}
static inline uint8_t inb(uint16_t port)
@@ -280,8 +314,13 @@ static void render(int c0, int c1) {
//draw_string("If this is displayed, my code works.", 100+c0, 100+c1, 16777215);
}
+#if 0
extern "C" void main(){
-
+#else
+extern "C" void main(struct VBE_modeInfo *vbe) {
+   modeInfoPointer = vbe;
+#endif
+
int clock = 0;
int incC1 = 0;
int incC0 = 0;

相关内容

  • 没有找到相关文章

最新更新