Как изменить сегмент данных? Что я делаю неправильно?

Я занимаюсь разработкой 32-битной ОС и разработал работающий загрузчик ELF, который работает просто отлично. Теперь у меня не включена подкачка страниц (я планирую позже, но сейчас я просто пытаюсь загрузить модули ядра), и я пытаюсь запускать модули при загрузке. По сути, поскольку в настоящее время многозадачность еще не полностью реализована, я просто хочу загрузить каждый модуль, вызвать init (который установит обработчики прерываний и просто настроит то, для чего предназначен модуль), а затем выйдет и выполнит следующий. Это работает, но я ничего не могу сделать с указателями в программе C (потому что он все еще думает, что использует сегмент данных ядра). Поэтому в основном я хочу создать новый сегмент данных, который указывает на сегмент модулей.data в оперативной памяти. Я делаю это, устанавливая запись № 6 в GDT, как.

setGDTEntry(6, DataAddress,DataSize, 0xF2, 0xCF);

Метод setEntry работает просто отлично, похоже

void setGDTEntry(int num, uint Base, uint limit, byte access, byte gran)

Снова оба работают на 100%, проблема, которая у меня возникает, когда я меняю селектор сегмента данных. Я делаю это в сборке, точка входа ELF хранится в EAX.

mov ax, 30h ; This is 8 * 6, the GDT entry containing the new data segment
mov ds, ax ; set data segment
call address ; JUMP!!!!
mov ax, 0x10 ; Restore kernel data segment
mov ds, ax ; set data segment

Это заставит мое ядро ​​запаниковать, выдав процессор 0x6, недопустимый код операции. Исходный код моей программы на C - это просто программа hello world, которая копирует текст в видеопамять (ничего особенного не видно). Кто-нибудь знает, что я делаю не так? Я новичок во всей концепции GDT и селекторов сегментов.......... И я не могу включить пейджинг или многозадачность в это время, я действительно не хочу объяснять, почему....

1 ответ

Прежде всего, вам нужно установить не только ds, но также es а также ss, Если вы этого не сделаете, некоторые инструкции будут использовать ds.base в качестве основы сегмента (например, mov eax, [ebx]), в то время как другие будут использовать ss.base (например mov eax, [ebp+8]) или же es.base (например rep movsd) и они будут разными, что приведет к несовместимой адресации.

Другая проблема, которая может возникнуть cs (недопустимое исключение инструкции указывает на это). Код x86 вообще не зависит от позиции. Так же, как вы должны создать и использовать отдельный сегмент данных, чтобы компенсировать разницу между тем, где разделы данных загружаются в память и где они должны находиться в памяти (различные заголовки / разделы ELF сообщают вам об этом), вы должны сделать то же самое для раздела кода. Ты можешь измениться cs используя дальний вызов, дальний прыжок или дальний возврат.

Другие вопросы по тегам