我正在缓慢但稳定地开发一个小型操作系统,我终于认为我有了一些代码(理论上)输出到VESA VBE。然而,我在尝试编译时遇到了一系列错误。我确信我的代码有问题,尽管我不知道是什么问题。我看到了错误,但我不知道如何修复它们。有关更多相关信息,您可以查看一些源代码以了解我的混乱代码:
1.我从here得到了VBE_modeInfo
结构体
1.我从previous question中得到了u32 modeInfoPointer = asm volatile ("eax");
、u32 physical_address = modeInfo.PhysBasePtr + y * modeInfo.LinBytesPerScanLine + x * bytesPerPixel;
和很多汇编代码。
Here是我的一长串错误,如果有人好奇的话。我不认为boot.asm
是问题所在,因为我没有提到它。在这里,我将kernel.cpp
和我的GitHub留给其余的代码:
kernel.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;
}
编辑:我将在这里添加其余的相关代码。Shell文件和完整的src
在我的GitHub:
错误数:
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);
| ^~~~~~~~~~~
boot.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
1条答案
按热度按时间zte4gxcn1#
好吧,根据所有的热门评论...
我们希望从
eax
设置modeInfoPointer
,因为它保存了VBE指针。在
boot.asm
中,它从int 0x10
得到这个。但是,我们必须把它移到某个地方。当我们跳到start_protected_mode
并执行以下操作时,它会被重写:所以,我们需要(作为第一个指令的那一点):
然后,在
jmp KERNEL_LOCATION
之前,我们需要:此外,我们需要
call
而不是jmp
然后,在
kernel.cpp
中,我们需要:还有其他调整。
modeInfo
的使用与modeInfo.
和modeInfo->
* 不一致 *我已经尽我所能纠正了编译错误。几乎可以肯定它仍然是坏的,但应该会让你更进一步。
它应该解决了我们希望
modeInfoPointer
指向VBE块[AFAICT]的问题。在下面的代码中,我使用了
cpp
条件语句来表示旧代码和新代码:注意:可以通过
unifdef -k
运行文件来清除此问题下面是一个针对github回购协议的补丁: