编写我自己的内核 - 全局变量不起作用
Writing my own kernel - global variables not working
我正在编写我自己的内核(使用 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)
}
我不太熟悉自定义链接器脚本,所以我真的不知道自己在做什么,我什至不确定这是否是问题所在。
您需要 link .data
段并为其执行一些初始化代码,以便初始化 VGA_buffer
。这意味着您需要确保某种方式的 "CRT"(C 运行 时间)代码执行 .data
初始化。如果你 运行 某些 "no ABI" 版本的编译器,除非你自己手动编写,否则这部分可能根本不会发生。
丢弃 const
和 volatile
限定符会调用未定义的行为。不确定为什么首先添加 const
。
volatile static void* VGA_buffer = 0xb8000;
无效 C. 请参阅
迂腐地,总是在声明的开头写存储 class 说明符。 volatile static...
是过时的样式 C。相反,总是写 static volatile...
浪费了几个小时,因为我漏掉了两个字符:-c
在将我的 C 代码编译成 kernel.o
时,我忘记告诉 gcc
这是一个仅编译步骤,不应执行 linking。添加 -c
标志后,一切正常!
我在路上得到了很好的提示,但我从来没有注意到它们:
- 我想知道,在编译我的 C 代码时,为什么我必须输入
-nostdlib
来阻止标准库被 linked... 因为我忘记了 -c
旗帜.
- 我也想知道为什么它抱怨没有提供一些外部人员,因为它试图 link 在这一步不应该。
我正在编写我自己的内核(使用 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)
}
我不太熟悉自定义链接器脚本,所以我真的不知道自己在做什么,我什至不确定这是否是问题所在。
您需要 link .data
段并为其执行一些初始化代码,以便初始化 VGA_buffer
。这意味着您需要确保某种方式的 "CRT"(C 运行 时间)代码执行 .data
初始化。如果你 运行 某些 "no ABI" 版本的编译器,除非你自己手动编写,否则这部分可能根本不会发生。
丢弃 const
和 volatile
限定符会调用未定义的行为。不确定为什么首先添加 const
。
volatile static void* VGA_buffer = 0xb8000;
无效 C. 请参阅
迂腐地,总是在声明的开头写存储 class 说明符。 volatile static...
是过时的样式 C。相反,总是写 static volatile...
浪费了几个小时,因为我漏掉了两个字符:-c
在将我的 C 代码编译成 kernel.o
时,我忘记告诉 gcc
这是一个仅编译步骤,不应执行 linking。添加 -c
标志后,一切正常!
我在路上得到了很好的提示,但我从来没有注意到它们:
- 我想知道,在编译我的 C 代码时,为什么我必须输入
-nostdlib
来阻止标准库被 linked... 因为我忘记了-c
旗帜. - 我也想知道为什么它抱怨没有提供一些外部人员,因为它试图 link 在这一步不应该。