Assembler - язык неограниченных возможностей

         

Вход и выход из защищенного режима


Итак, чтобы перейти в защищенный режим, достаточно установить бит РЕ — нулевой бит в управляющем регистре CR0, и процессор немедленно окажется в защищенном режиме. Единственное дополнительное требование, которое предъявляет Intel, — чтобы в этот момент все прерывания, включая немаскируемое, были отключены.

; pm0.asm ; Программа, выполняющая переход в защищенный режим и немедленный возврат. ; Работает в DOS в реальном режиме и в DOS-окне Windows 95 (Windows ; перехватывает исключения, возникающие при попытке перехода в защищенный ; режим из V86, и позволяет нам работать, но только на минимальном уровне ; привилегий) ; ; Компиляция: ; TASM: ; tasm /m pm0.asm ; tlink /x /t pm0.obj ; MASM: ; ml /c pm0.asm ; link pm0.obj,,NUL,,, ; exe2bin pm0.exe pm0.com ; WASM: ; wasm pm0.asm ; wlink file pm0.obj form DOS COM

.model tiny .code .386p ; все наши примеры рассчитаны на 80386 org 100h ; это СОМ-программа start: ; подготовить сегментные регистры push cs pop ds ; DS - сегмент данных (и кода) нашей программы push 0B800h pop es ; ES - сегмент видеопамяти ; проверить, находимся ли мы уже в защищенном режиме mov еах,cr0 ; прочитать регистр CR0 test al,1 ; проверить бит РЕ, jz no_V86 ; если он ноль - мы можем продолжать, ; иначе - сообщить об ошибке и выйти mov ah,9 ; функция DOS 09h mov dx,offset v86_msg ; DS:DX - адрес строки int 21h ; вывод на экран ret ; конец СОМ-программы ; (раз это защищенный режим, в котором работает наша DOS-программа, это должен ; быть режим V86) v86_msg db "Процессор в режиме V86 - нельзя переключиться в РМ$"

; сюда передается управление, если мы запущены в реальном режиме no_V86: ; запретить прерывания cli ; запретить немаскируемое прерывание in al,70h ; индексный порт CMOS or al,80h ; установка бита 7 в нем запрещает NMI out 70h,аl ; перейти в защищенный режим mov еах,cr0 ; прочитать регистр CRO or al,1 ; установить бит РЕ, mov cr0,eax ; с этого момента мы в защищенном режиме ; вывод на экран xor di,di ; ES:DI - начало видеопамяти mov si,offset message ; DS:SI - выводимый текст mov cx,message_l rep movsb ; вывод текста mov ax,0720h ; пробел с атрибутом 07h mov cx,rest_scr ; заполнить этим символом остаток экрана rep stosw ; переключиться в реальный режим mov еах,cr0 ; прочитать CR0 and al,0FEh ; сбросить бит РЕ mov cr0,eax ; с этого момента процессор работает в ; реальном режиме ; разрешить немаскируемое прерывание in al,70h ; индексный порт CMOS and al,07Fh ; сброс бита 7 отменяет блокирование NMI out 70h,al ; разрешить прерывания sti ; подождать нажатия любой клавиши mov ah,0 int 16h ; выйти из СОМ-программы ret ; текст сообщения с атрибутом после каждого символа для прямого вывода на экран message db 'Н',7,'е',7,'l',7,'l',7,'о',7,' ',7,'и',7,'з',7 db ' ',7,'Р',7,'М',7 ; его длина в байтах message_l = $ - message ; длина оставшейся части экрана в словах rest_scr = (80*25)-(2*message_l) end start


В главе 6.1 при рассмотрении адресации в защищенном режиме говорилось о том, что процессор, обращаясь к памяти, должен определить адрес начала сегмента из дескриптора в таблице дескрипторов, находящейся в памяти, используя селектор, находящийся в сегментном регистре, в качестве индекса. В то же время в этом примере мы обращаемся к памяти из защищенного режима, вообще не описав никаких дескрипторов, и в сегментных регистрах у нас находятся те же числа, что и в реальном режиме.

Дело в том, что, начиная с процессора 80286, размер каждого сегментного регистра — CS, SS, DS, ES, FS и GS — не два байта, а десять, восемь из которых недоступны для программ, точно так же, как описанные выше регистры LDTR и TR. В защищенном режиме при записи селектора в сегментный регистр процессор копирует весь определяемый этим селектором дескриптор в скрытую часть сегментного регистра и больше не пользуется этим селектором вообще. Таблицу дескрипторов можно уничтожить, а обращения к памяти все равно будут выполняться, как и раньше. В реальном режиме при записи числа в сегментный регистр процессор сам создает соответствующий дескриптор в его скрытой части. Этот дескриптор описывает 16-битный сегмент, начинающийся по указанному сегментному адресу с границей 64 Кб. Когда мы переключились в защищенный режим в программе pm0.asm, эти дескрипторы остались на месте и мы могли обращаться к памяти, не принимая во внимание то, что у нас написано в сегментном регистре. Разумеется, в этой ситуации любая попытка записать в сегментный регистр число привела бы к немедленной ошибке (исключение #GP с кодом ошибки, равным загружаемому значению).


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