Защищенный режим процессоров Intel 80286 80386 80486

       

Недокументированная команда LOADALL


Оказывается, для процессора i80286 существует способ получения доступа к расширенной памяти, не переключаясь в защищённый режим. Для этого может быть использована недокументированная команда LOADALL, имеющая код 0F05h (команда не имеет операндов). Эта команда не описана в справочниках по процессору i80286, информация о ней поставляется фирмой Intel по запросу. Те сведения о команде LOADALL, которые приведены в нашей книге, получены по электронной почте из BBS и могут быть использованы только для расширения вашего кругозора и для оценки полезности этой команды в ваших разработках.

Команда LOADALL первоначально была задумана фирмой Intel как тестовая. Однако оказалось, что она пригодна и для обращения к расширенной памяти в реальном режиме. Широко известный драйвер расширенной памяти HIMEM.SYS обращается в область адресов выше первого мегабайта именно с помощью команды LOADALL (а не переключаясь в защищённый режим и возвращаясь обратно, как это можно было бы предположить).

Команда LOADALL сокращает время, требуемое драйверу HIMEM.SYS на доступ к расширенной памяти, так как время на переключение в защищённый режим и обратное переключение достаточно велико по сравнению с временем, необходимым на копирование данных из основной памяти в расширенную или обратно.

Другое применение команды - драйвер электронного диска Microsoft RAMDRIVE.SYS и блок совместимости операционной системы Microsoft OS/2 версии 1.x.

Секрет команды LOADALL заключается в том, что она загружает ВСЕ регистры процессора, и может выполняться в реальном режиме. Изменяя поле базы регистра кэша дескриптора (внутренний системный регистр процессора) программа может обратиться к сегменту, лежащему за пределами первого мегабайта адресного пространства.

Как мы уже говорили, команда LOADALL не имеет операндов. Регистры загружаются из буфера, который имеет длину 102 байта и должен быть подготовлен в области памяти с физическим адресом 00800h.

Формат буфера представлен в следующей таблице:

Таблица 16. Формат буфера для команды LOADALL.



АдресРегистры процессора
800h-805hНе используется
806h-807hСлово состояния процессора MSW (Machine Status Word)
808h-815hНе используется
816h-817hРегистр задачи TR (Task Register)
818h-819hРегистр флагов
81Ah-81BhРегистр IP (Instruction Pointer)
81Ch-81DhСелектор LDT (Local Descriptor Table)
81Eh-81FhРегистр DS (Data Segment Selector)
820h-821hРегистр SS (Stack Segment Selector)
822h-823hРегистр CS (Code Segment Selector)
824h-825hРегистр ES (Extra Segment Selector)
826h-827hРегистр DI (Destination Index)
818h-829hРегистр SI (Source Index)
82Ah-82BhРегистр BP (Base Pointer)
82Ch-82DhРегистр SP (Stack Pointer)
82Eh-82FhРегистр BX (Data Register BX)
830h-831hРегистр DX (Data Register DX)
832h-833hРегистр CX (Data Register CX)
834h-835hРегистр AX (Accumulator)
836h-83BhКэш дескриптора ES
83Ch-841hКэш дескриптора CS
842h-847hКэш дескриптора SS
848h-84DhКеш дескриптора DS
84Eh-853hРегистр GDTR (Global Descriptor Table Register)
854h-859hКэш дескриптора LDT
85Ah-85FhРегистр IDTR (Interrupt Descriptor Table Register)
860h-865hКэш дескриптора TSS (Task State Segment)

Для ускорения доступа к содержимому дескрипторных таблиц в процессоре имеются так называемые теневые регистры или регистры кэша дескрипторов.
Когда процессор загружает селектор в сегментный регистр, автоматически выполняется загрузка соответствующего регистра кэша дескриптора. Не существует какого-либо иного способа загрузить кэш дескриптора явно из программы с помощью обычных команд. Однако вы можете воспользоваться для этого командой LOADALL, подготовив в описанном выше буфере необходимые значения. Формат кэша дескриптора приведён в следующей таблице:
Таблица 17. Формат кэша дескриптора.

Смещение поляНазначение поля
0-224-битовый базовый адрес сегмента
3Байт доступа, его формат полностью аналогичен формату байта доступа дескриптора, за исключением бита присутствия. На месте этого бита находится бит VALID. Если этот бит сброшен в 0, при попытке использовать дескриптор для адресации памяти произойдёт исключение 13 с кодом ошибки 0.
4-516-битовый предел сегмента
Можно предложить следующий алгоритм использования команды LOADALL:
  • Запретитите прерывания.
  • Сохраните где-нибудь в буфере программы область памяти, начинающуюся с адреса 00800h и имеющую длину 102 байта.
  • Заполните буфер для команды LOADALL необходимыми значениями для всех загружаемых регистров. Базовый адрес в области кэша дескриптора сегмента данных должен указывать на необходимый вам участок расширенной памяти.
  • Выполните команду LOADALL. Сегмент данных теперь будет указывать на область расширенной памяти.
  • Выполните запись или чтение области расширенной памяти.
  • Восстановите базовый адрес сегмента данных в кэше дескриптора данных в буфре, расположенном по адресу 00800h.
  • Выполните команду LOADALL ещё раз.
  • Восстановите содержимое сохранённого ранее буфера.
  • Разрешите прерывания.
При выполнении команды LOADALL не делается никаких проверок. Вам необходимо самим позаботиться о том, чтобы загружаемые в регистры процессора значения имели какой-нибудь смысл. В противном случае состояние процессора окажется непредсказуемым. Команда LOADALL может выполняться в защищённом режиме в нулевом приоритетном кольце. Но, к сожалению, эту команду нельзя использовать для переключения процессора из защищённого в реальный режим. Процессор i80387 также имеет команду LOADALL, но её код и выполняемые функции другие.

Содержание раздела