为什么这个内核会导致问题?
Why is this kernel causing problems?
我决定尝试编写一个 C Hello world 保护模式内核,虽然直接访问视频内存可以手动打印字符,但我决定尝试编写一个字符串,并且没有警告或错误但是它引导到闪烁的光标,但大约半毫秒后它黑屏。
这是代码:
#include <stdint.h>
void kmain() {
// Startup
int i = 0;
uint16_t* vidmem = (uint16_t*) 0xB8000;
char string[] = "Hello, kernel world!";
while (string[i]) {
vidmem[i] = string[i];
vidmem[i+1] = 0;
i+=2;
}
// Hang the system
for (;;) {
}
}
编译:gcc -m32 -c kernel.c -o kernel.o -std=gnu99 -ffreestanding -O1 -Wall -Wextra
然后与通用链接boot.o,然后用 grub
制作成 ISO
我在 linux 上用 qemu 测试了它,任何帮助将不胜感激!
在我尝试打印字符串功能之前,它能够打印字符:
vidmem[0] = "C";
vidmem[1] = 1;
这会打印字母 C。虽然没有什么特别的。
在尝试修复一些错误后,我想到了这个:
#include <stdint.h>
void kmain() {
// Startup
int i = 0;
int j = 0;
uint16_t* vidmem = (uint16_t*) 0xB8000;
char string[] = "Hello, kernel world!";
while (string[i]) {
vidmem[i] = string[i];
vidmem[j] = 0;
i+=1;
j=i*2;
}
// Hang the system
for (;;) {
}
}
还是黑屏
两个版本都不正确;
uint8_t* vidmem = (uint8_t*) 0xB8000;
char string[] = "Hello, kernel world!";
for(size_t i = 0; string[i]; i++) {
vidmem[i*2] = string[i];
vidmem[i*2 + 1] = 0;
}
你太努力了,没有做不需要的算术。请记住,C 中的指针算术和数组索引始终以所指向类型的大小为单位。如果您想将 string
的字节复制到 vidmem
中,每个字节后有一个零字节,那么由于 x86 上的整数是小端字节序这一事实,这样做就足够了
int i = 0;
uint16_t* vidmem = (uint16_t*) 0xB8000;
unsigned char string[] = "Hello, kernel world!";
while (string[i]) {
vidmem[i] = string[i];
i++;
}
或者如果您愿意
for (i = 0; string[i]; i++)
vidmem[i] = string[i];
就是这样。
如果您想要一种不是黑底黑字的不同颜色,您可以将其更改为 vidmem[i] = string[i] | 0x7000;
。
我决定尝试编写一个 C Hello world 保护模式内核,虽然直接访问视频内存可以手动打印字符,但我决定尝试编写一个字符串,并且没有警告或错误但是它引导到闪烁的光标,但大约半毫秒后它黑屏。 这是代码:
#include <stdint.h>
void kmain() {
// Startup
int i = 0;
uint16_t* vidmem = (uint16_t*) 0xB8000;
char string[] = "Hello, kernel world!";
while (string[i]) {
vidmem[i] = string[i];
vidmem[i+1] = 0;
i+=2;
}
// Hang the system
for (;;) {
}
}
编译:gcc -m32 -c kernel.c -o kernel.o -std=gnu99 -ffreestanding -O1 -Wall -Wextra
然后与通用链接boot.o,然后用 grub
制作成 ISO我在 linux 上用 qemu 测试了它,任何帮助将不胜感激!
在我尝试打印字符串功能之前,它能够打印字符:
vidmem[0] = "C";
vidmem[1] = 1;
这会打印字母 C。虽然没有什么特别的。
在尝试修复一些错误后,我想到了这个:
#include <stdint.h>
void kmain() {
// Startup
int i = 0;
int j = 0;
uint16_t* vidmem = (uint16_t*) 0xB8000;
char string[] = "Hello, kernel world!";
while (string[i]) {
vidmem[i] = string[i];
vidmem[j] = 0;
i+=1;
j=i*2;
}
// Hang the system
for (;;) {
}
}
还是黑屏
两个版本都不正确;
uint8_t* vidmem = (uint8_t*) 0xB8000;
char string[] = "Hello, kernel world!";
for(size_t i = 0; string[i]; i++) {
vidmem[i*2] = string[i];
vidmem[i*2 + 1] = 0;
}
你太努力了,没有做不需要的算术。请记住,C 中的指针算术和数组索引始终以所指向类型的大小为单位。如果您想将 string
的字节复制到 vidmem
中,每个字节后有一个零字节,那么由于 x86 上的整数是小端字节序这一事实,这样做就足够了
int i = 0;
uint16_t* vidmem = (uint16_t*) 0xB8000;
unsigned char string[] = "Hello, kernel world!";
while (string[i]) {
vidmem[i] = string[i];
i++;
}
或者如果您愿意
for (i = 0; string[i]; i++)
vidmem[i] = string[i];
就是这样。
如果您想要一种不是黑底黑字的不同颜色,您可以将其更改为 vidmem[i] = string[i] | 0x7000;
。