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

时间:2020-03-27 14:10:36

标签: c x86 kernel ld osdev

我正在编写自己的内核(使用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)
}

我对自定义链接描述文件不是很熟悉,所以我真的不知道自己在做什么,而且我不确定这是否是问题所在。

2 个答案:

答案 0 :(得分:2)

您需要链接.data段并为其执行一些初始化代码,才能初始化VGA_buffer。这意味着您需要确保某种方式的“ CRT”(C运行时)代码执行.data初始化。如果您运行某些“ no ABI”版本的编译器,那么除非您亲自编写,否则此部分可能根本不会发生。

放弃constvolatile限定词会导致未定义的行为。不确定为什么要首先添加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标志后,一切正常!

路上,我得到了很多提示,但我什至从未注意到它们:

  • 我想知道为什么在编译C代码时为什么必须放入-nostdlib才能阻止标准库的链接……因为我忘记了-c标志。
  • 我还想知道为什么它抱怨没有提供一些外部信息,因为它在本不应该这样做的这一步试图进行链接。
相关问题