[Назад] [Далее]

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

Итак, чтобы перейти в защищенный режим, достаточно установить бит РЕ — нулевой бит в управляющем регистре 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 с кодом ошибки, равным загружаемому значению).


п»ї
"target=_blank><\/a>") //-->