Надеюсь, у вас все хорошо во время конфайнмента.
В качестве краткого вступления: я пишу этот вопрос не как Tretorn, а как член ASO C, ассоциации студентов-информатиков из Испании. Мы пытаемся узнать, как работают ядра, самостоятельно разрабатывая их. У нас есть весь код (связанный с вопросом), опубликованный в https://github.com/TretornESP/ASOC2
Поскольку у нас около 30 учеников, мы разделили работу на: файловую систему, память, программное обеспечение пользовательского пространства (просто оболочка), Управление процессами и Bootloader.
Когда мы один месяц в разработке, мы столкнулись с некоторыми реальными проблемами в этой последней части, поэтому здесь я прошу вас о некоторой помощи по этому вопросу.
Шаги, которые мы выполняем с того момента, как B IOS настраивает нас на 0x7c00
:
- Установите CS, выполнив прыжок в длину (Спасибо, мистер Петч!)
- Сохранить основной диск
- Установить 16-битный стек
- Загрузить 8 секторов с диска (2-й этап)
- Загрузить 32-битный GDT
- Загрузить IDT
- Включить защищенный режим (CR0)
- Выполнить дальний переход к конвейеру flu sh и установить CS
- Установить все сегменты одинаково (Плоская сегментация)
- Установить новый стек в
0x90000
- Обнаружить присутствие LM через CPUID
- Отключить старый пейджинг (мы не делали настроить подкачку в PM)
- настроить таблицы страниц
- активировать PAE
- активировать LM
- включить подкачку
- загрузить GDT (аналогично как в 32 битах, может быть в режиме сжатия?)
- Дальний переход по тем же причинам, что и выше
- Обновление сегментов
- Сброс стека
- Вызов C kmain via
extern kmain call kmain
Наш скрипт компоновщика:
OUTPUT_FORMAT("binary");
ENTRY(boot);
SECTIONS
{
. = 0x7C00;
.text : {
*(.boot);
*(.text);
}
.rodata : SUBALIGN(4) {
*(.rodata);
}
.data : SUBALIGN(4) {
*(.data);
}
.bss : SUBALIGN(4) {
*(.bss)
}
/DISCARD/ : {
*(.eh_frame);
*(.comment);
*(.note.gnu.build-id);
}
}
, который мы компилируем с:
nasm -f elf64 boot.asm -o boot.o
gcc -ffreestanding -nostdlib -mno-red-zone -fno-exceptions -m64 kernel.c boot.o -o kernel.bin -T link.ld
и тестируем с помощью:
qemu-system-x86_64 -fda kernel.bin
Наш kmain вроде пишет в VGA, если мы устанавливаем функцию следующим образом:
void kmain() {
char * vga_ptr = (char*)0xb8000;
*(vga_ptr++) = 0x0f;
*(vga_ptr++) = 'H';
while (1){}
}
Но если вместо этого я объявляю vga_ptr
за пределами kmain
границ, процессор сбрасывает выполнение.
Предположение, которое я здесь делаю, состоит в том, что ЦП имеет тройной отказ, учитывая тот факт, что IDT неполна (любая помощь в этом тоже будет признательна). Вопрос больше в том, что вызывает исключение, которое вызывает двойной отказ, тройной отказ, сброс салазок в первую очередь. Я просто догадываюсь, но, возможно, это связано с неправильным подкачкой или процессом сборки (друг link.ld
доставил нам много проблем в прошлом).
Любой свет залил эту проблему или указал на любой беспорядок обнаружен в нашем коде будет принята с благодарностью. И мне жаль, если вопрос был слишком длинным или неточным. Помните, что мы действительно студенты (;
Хорошего дня и будьте в безопасности!
PS Полный код загрузчика приведен выше в github, в ветке BootTest. Я пытался сделайте вопрос как можно короче, но по запросу я могу отредактировать текст, включив в него любой фрагмент кода, который вам нужен.
[РЕДАКТИРОВАТЬ] Еще одна ошибка, возможно, не связанная с тем, что, когда я разбираю файл .bin, он показывает все в разделе .data
.