我正在编写自己的内核(使用multiboot2),并遵循this tutorial使其进入长模式。我现在与以下C代码链接:
void kernel_main()
{
*(uint64_t*) 0xb8000 = 0x2f592f412f4b2f4f;
}
这会将OKAY
打印到屏幕上。
但是,我现在创建一个名为VGA_buffer
的全局变量来保存该内存地址。
volatile static const void* VGA_buffer = 0xb8000;
void kernel_main()
{
*(uint64_t*) VGA_buffer = 0x2f592f412f4b2f4f;
}
该代码不再起作用,OKAY
不在屏幕上。
我该如何解决?
我认为这是因为我的链接描述文件不包括全局变量数据。这就是我所拥有的:
ENTRY(start)
SECTIONS
{
. = 1M;
.boot :
{
*(.multiboot_header)
}
.text :
{
*(.text)
}
}
我也尝试添加以下内容:
...
.rodata :
{
*(.rodata)
}
.data :
{
*(.data)
}
.bss :
{
*(.bss)
}
我对自定义链接描述文件不是很熟悉,所以我真的不知道自己在做什么,而且我不确定这是否是问题所在。
答案 0 :(得分:2)
您需要链接.data
段并为其执行一些初始化代码,才能初始化VGA_buffer
。这意味着您需要确保某种方式的“ CRT”(C运行时)代码执行.data
初始化。如果您运行某些“ no ABI”版本的编译器,那么除非您亲自编写,否则此部分可能根本不会发生。
放弃const
和volatile
限定词会导致未定义的行为。不确定为什么要首先添加const
。
volatile static void* VGA_buffer = 0xb8000;
无效C。请参见"Pointer from integer/integer from pointer without a cast" issues
通常,始终在声明的开头编写存储类说明符。 volatile static...
是过时的样式C。相反,请始终写static volatile...
答案 1 :(得分:1)
浪费时间是因为我缺少两个字符:-c
将我的C代码编译为kernel.o
时,我忘记告诉gcc
这是仅编译的步骤,不应进行任何链接。添加-c
标志后,一切正常!
路上,我得到了很多提示,但我什至从未注意到它们:
-nostdlib
才能阻止标准库的链接……因为我忘记了-c
标志。