Глава 9. Вход в защищённый режимКогда программа переводит процессор в защищённый режим, при всём том богатом потенциале, который предоставляют 32-разрядные процессоры, она оказывается практически беспомощной. В основном это связано с тем, что в защищённом режиме совершенно другая система прерываний и воспользоваться ресурсами, предоставляемыми операционной системой, в которой вы запускаете такую программу, невозможно. Более того, недоступными окажутся прерывания BIOS и IRQ. Подробно работа прерываний описана в разделе "Прерывания в защищённом режиме", там же вы найдёте примеры использования прерываний всех типов (программные, аппаратные и исключения), но пока наша программа не сможет ими воспользоваться. Прежде, чем мы перейдём к примеру, давайте определимся с тем, что нам надо сделать:
В третьем пункте мы заставим программу вывести на экран строку "I am in protected mode!!!", после чего программа зациклит процессор (компьютер повиснет). Дело в том, что возврат в режим реальных адресов немного сложнее, чем переход в защищённый режим и это требует дополнительного объяснения, поэтому в этом примере приводится только переход в P-Mode. Хочу обратить ваше внимание на то, что первой командой после перехода в защищённый режим должна быть команда дальнего перехода (far jump), в которой будет указан селектор дескриптора сегмента кода и смещение в этом сегменте. При работе в защищённом режиме процессор может использовать в сегментных регистрах только селекторы существующих дескрипторов, любые другие значения (например, сегментный адрес) использовать нельзя - процессор сгенерирует исключение общей защиты. Тем не менее, при переходе в защищённый режим регистр CS будет содержать сегментный адрес, который использовался в режиме реальных адресов, поэтому выполнение следующей команды, какой бы она ни была, должно было бы привести к генерации процессором исключения. На самом деле этого не происходит, так как эта команда не выбирается из памяти - она уже находится в конвейере процессора (даже в таком процессоре, как i386, есть конвейер) и поэтому вы можете выполнить эту команду. Использование ошибок процессоров не представляется мне практичным, т.к. вариаций одной и той же модели процессоров много - десятки, хотя если вы сможете найти достойное применение ошибкам, то я буду рад опубликовать на сайте ваши статьи. И всё же, возвращаясь к примеру, давайте определимся: мы изучаем "правильное" программирование 32-разрядных процессоров, при этом не используя никаких ошибок в архитектуре и никаких недокументированных особенностей и команд. Это нам обеспечит уверенность в том, что наши программы будут надёжно работать на любых интеловских процессорах и их клонах. Прежде, чем мы перейдём к примеру программы, давайте определим две функции, которые мы будем в дальнейшем использовать. В программе нам понадобится создавать 4 дескриптора - для кода, данных (где будет хранится выводимая строка), стека (он будет использоваться для вызова функции вывода текста) и видеопамяти. Все дескрипторы сегментов подобны друг другу, поэтому удобно их будет создавать отдельной функцией. Исходный код для этой функции (и для второй) поместите как макросы в отдельный файл - мы их будем использовать в дальнейшем и просто подключать к исходникам. Функция первая, "set_descriptor" предназначенная для создания дескриптора, приводится сразу в том виде, в каком она будет находится в подключаемом файле "pmode.lib". При вызове этой функции подразумевается, что в паре регистров DS:BX находится указатель на текущую позицию в GDT. Функция после создания дескриптора переведёт указатель на позицию для следующего дескриптора. Все необходимые параметры передаются через регистры и функция всего лишь "перетасовывает" их в нужном порядке.
Вторую функцию "putzs" добавьте в файл "pmode.lib" после описания первой. Эта функция предназначена для вывода на экран строки, оканчивающейся нулевым байтом (т.е. байтом, равным 00h). Такая строка везде на этом сайте называется ZS-строка или просто ZS (от Zero-String). Также вам будут встречаться строки другого типа - LS (от Lenght-String), длина которых будет задана первым байтом.
Теперь сам пример. Прежде чем приступить к его изучению, хочу сделать следующие замечания:
Далее полностью приводится файл "example2.asm", который содержит пример перехода в защищённый режим, включая необходимые для tasm-а атрибуты.
|