Почему я не могу вызвать прерывания BIOS из защищенного режима?
Right. Сегодня я потратил более трех часов, пытаясь понять, почему вы не можете вызывать bios ISR в защищенном режиме. Я получаю, что после того, как вы установили и IDT, он не обязательно будет в обычном адресе для сегментов IVT plus, не имеет фиксированного размера в защищенном режиме и т.д. Но я до сих пор не понимаю, почему вы не можете создать один 4 ГБ сегмент, сопоставьте сегменты IDT с BIOS IVT, установите все в кольце 0 и вызовите их. Разве это не работает?
Большинство статей либо говорят: "Помните, вы не можете использовать прерывания BIOS в защищенном режиме!" без изучения предмета или чрезвычайно описательных и цитирующих ловушек, исключений, ремаркетинга фото, отсутствия прав и проблем с сегментными регистрами в качестве причины этого.
Было бы очень полезно, если бы кто-нибудь мог придумать более дружелюбное для человека объяснение... Я не сомневаюсь в том, что говорят статьи, я просто хочу понять, почему это такая "боль"!
Спасибо заранее!
Ответы
Ответ 1
Я думаю, что самая большая проблема заключается в том, что процедуры BIOS были написаны в предположении, что процессор находится в реальном режиме. Если вы вызываете их из неподдерживаемого контекста, вы не можете быть уверены, что процедуры BIOS будут вести себя так, как ожидалось. Они могут потерпеть неудачу самостоятельно или могут испортить состояние процессора и выбить вас из защищенного режима.
Ответ 2
Max, вы могли бы создать драйвер устройства, работающий в кольце 0, который вызывает более простой BIOS ISR, если ОС работает в 16-разрядном защищенном режиме. Но в 32-битном режиме первое 16- или 32-битное смещение адреса или немедленное значение будут интерпретироваться некорректно, и поток команд перестанет синхронизироваться. В реальном или 16-битном защищенном режиме значения немедленного и смещения по умолчанию 16 бит в длину, в 32-битном защищенном режиме они имеют длину 32 бита, а в 64-разрядном (длинном) режиме они представляют собой 32 или 64 бита длинный. Таким образом, в ISR могут использоваться только смещения, представленные в виде байтов (< 128, если я правильно помню) и байтовых мгновенных значений.
Кроме того, любая загрузка регистрового регистра (отличная от нуля) будет вести себя по-разному в реальном режиме, чем в любом защищенном режиме. Опять же, код реального режима и код защищенного режима могут работать вместе, чтобы можно было писать код, который работает, но это совсем не легко.
Например, `
mov ah, 0B8h
mov al, 000h
mov es, ax
mov byte ptr es:0, 'o'
mov byte ptr es:2, 'k'`
поместит буквы "ok" в верхнем левом углу экрана текстового режима в реальном режиме, но чтобы эта работа работала в 16-битном или 32-битном защищенном режиме, запись таблицы глобального дескриптора со смещением 0xB800 должна имеют базовый адрес 0x000B8000.
Но если вас устраивает запуск только в 16-битном защищенном режиме, более распространенный код: `
mov ax, 0B800h
mov es, ax
mov dword ptr es:0, 0076b076fh`
должен работать так же хорошо.
Ответ 3
Я возвращаюсь к старым материалам, так что это может быть немного отключено, но одной из основных целей "защищенного" режима является выделение конфиденциального/защищенного кода из кода приложения. Первоначальная спецификация имела 4 уровня от 0 до кольца 3. На практике я видел только кольцо 0 для операционной системы и кольцо 3 для приложений. Разрешение приложениям изменять или вызывать прерывания может потенциально предложить им задний ход в операционную систему. Таким образом, такие операции доступны только для кода, выполняющегося в кольце 0, а именно в операционной системе. Единственный способ заставить ваш код работать в кольце 0 - это создать драйвер. Windows будет в основном загружать драйверы в свою собственную частную память ядра (хотя это имеет/меняется в Windows Vista/7), работающем в кольце 0.