编写我自己的内核 - 全局变量不起作用

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" 版本的编译器,除非你自己手动编写,否则这部分可能根本不会发生。

丢弃 constvolatile 限定符会调用未定义的行为。不确定为什么首先添加 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 在这一步不应该。