Пишу свое собственное ядро ​​- глобальные переменные не работают - PullRequest
1 голос
/ 27 марта 2020

Я пишу свое собственное ядро ​​(используя multiboot2) и следую этому руководству , чтобы перевести его в long-mode. Теперь я связываюсь со следующим 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 ]

2 голосов
/ 27 марта 2020

Вам необходимо связать сегмент .data и выполнить для него некоторый код инициализации, чтобы инициализировать VGA_buffer. Это означает, что вам нужно убедиться, что какой-то код "CRT" (C run-time) выполняет инициализацию .data. Если вы запустите какую-то версию компилятора «без ABI», эта часть может вообще не произойти, если вы не напишите ее вручную.

Отбрасывание квалификаторов const и volatile вызывает неопределенное поведение. Не уверен, почему вы добавили const во-первых.

volatile static void* VGA_buffer = 0xb8000; недействительно C. См. «Указатель от целого числа / целое число от указателя без приведения»

Педантично, всегда пишите спецификатор класса хранения в начале объявления. volatile static... - это устаревший стиль C. Вместо этого всегда пишите static volatile...

1 голос
/ 28 марта 2020

Часы потрачены впустую, потому что мне не хватало двух символов: -c

При компиляции моего кода C в kernel.o я забыл сказать gcc, что это был только этап компиляции и что ссылки не должны быть сделаны. После добавления флага -c все заработало!

И я получил отличные подсказки, но даже не заметил их:

  • Мне было интересно, когда я компилировал мой C код, почему я должен был вставить -nostdlib, чтобы предотвратить связывание стандартной библиотеки ... потому что я забыл флаг -c.
  • Мне также было интересно, почему он жаловался, что некоторые внешние не предоставлено, потому что он пытался связать на этом этапе, когда это не должно было быть.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...