Переключение между R-Mode и Р-Mode



В защищённый режим процессор надо переводить специальными операциями над системными регистрами и войти в этот режим процессор может только из режима реальных адресов, поэтому программа должна выполняться из простой операционной системы, работающей в режиме реальных адресов (MS-DOS). Если запустить программу из-под ОС, работающей в защищённом режиме (Windows), то программа не заработает, т.к. процессор уже будет работать в P-Mode и не допустит повторного входа в этот режим.

Все 32-разрядные процессоры, начиная с i386, имеют набор системных регистров, предназначенных для использования в защищённом режиме. Среди них есть регистры управления (Control Registers) CR0, CR1, CR2, CR3 и CR4.

   Регистры управления, в основном, состоят из флагов. Назначение и использование каждого флага достаточно сложно и требует отдельного рассмотрения. Единственная команда, которой позволен доступ к этим регистрам - это MOV, в качестве операнда которой используется 32-разрядный регистр общего назначения.

  Для перехода в защищённый режим и возврат из него в режим реальных адресов, используется только один бит из регистра CR0 - это нулевой бит, который называется PE (Protection Enable). Если установить этот бит в 1, процессор перейдёт в защищённый режим, если сбросить - то в режим реальных адресов.

Перевод процессора в защищённый режим:

    mov eax,cr0  ; Копируем в EAX содержимое регистра CR0.

    or al,1        ; Устанавливаем в копии 0-й бит, который

                                 ; соответствует 0-му биту CR0, т.е. биту PE.

    mov cr0,eax  ; Записываем в CR0 обновлённое значение.

Перевод процессора в режим реальных адресов:

    mov eax,cr0

    and al,0feh   ; Сбрасываембит PE.

    mov cr0,eax  ; Процессор перешёл в режим реальных адресов

Описание программы переключения режимов

Программа выполняет следующие действия: подготовиться к переходу в P-Mode, перейти в P-Mode, сообщить в программе о переходе в P-Mode. В таблице дескрипторов описано столько дескрипторов, сколько сегментов использует программа. В программе в таблицу включены, кроме обязательного нулевого дескриптора, всегда занимающего первое место в таблице, четыре дескриптора для сегментов данных, команд, стека и дополнительного сегмента данных, который мы наложим на видеобуфер. Вывод на экран будет выполняется прямой записью в видеопамять, для чего создана процедура.

  Первой командой после перехода в защищённый режим должна быть команда дальнего перехода (far jump), в которой указан селектор дескриптора сегмента кода и смещение в этом сегменте. Однако, при переходе в защищённый режим регистр CS будет содержать сегментный адрес, который использовался в режиме реальных адресов, поэтому выполнение следующей команды должно было бы привести к генерации процессором исключения. Но этого не происходит, так как эта команда не выбирается из памяти - она уже находится в конвейере процессора. Команда дальнего перехода очистит конвейер процессора, заставит его обратится к таблице GDT, выбрать оттуда дескриптор, селектор которого указан в адресе команды и начать выборку команд со смещения, указанного в этом адресе. Приведенные в программе комментарии облегчают понимание механизма защищенного режима.

Программа для включения защищённого режима и возврата в режим реальных адресов.

.386p ;для использования привилегированных команд

; 16-битный сегмент, в нем находится код для входа и выхода из защищенного режима

pmode segment use16

                   assume      cs:pmode, ds:pmode, es:pmode

                   org 100h ; СОМ, без потери общности

main          proc far

start:

; селекторы определяем как константы. У всех из них биты TI = 0 (выборка дескрипторов

;выполняется из GDT), RPL = 00B - уровень привилегий - нулевой.

Code_selector       = 8

Stack_selector       = 16

Data_selector = 24

Screen_selector= 32

R_Mode_Code= 40; Селектордескрипторасегментакода

R_Mode_Data= 48; Селектор дескриптора сегментов стека и данных.

; Сохраняем сегментные регистры, для возврата в R-Mode:

       mov R_Mode_SS,ss

       mov R_Mode_DS,ds

       mov R_Mode_ES,es

       mov R_Mode_FS,fs

       mov R_Mode_GS,gs

; Подготавливаем адрес возврата в R-Mode:

       mov R_Mode_segment,cs

       lea  ax,R_Mode_entry

       mov R_Mode_offset,ax

; если работать с 32-битной - памятью открываем линию А20:

       in    AL,92h

       or   AL,2

       out  92h,AL

; Очистим экран

       mov ax,3            ; clear screen

       int   10h

; Подготовка к переходу в защищённый режим:

       mov bx,offsetGDT + 8 ; Нулевой дескриптор не устанавливаем - не используется

       xor  eax,eax; EAX = 0

       mov edx,eax; EDX = 0

       push cs

       pop ax   ; AX = CS = сегментный адрес текущего сегмента кода.

       shl  eax,4; EAX = физический адрес начала сегмента кода.

; Эта программа, работая в среде операционной системы режима реальных адресов

;(подразумевается, MS-DOS) уже имеет в IP смещение относительно текущего сегмента

;кода. Определим дескриптор кода для защищённого режима с таким же адресом

;сегмента кода, чтобы при переходе через команду дальнего перехода фактически

;переход произошёл на следующую команду.

       mov dx,1024; Предел сегмента кода может быть любым, лишь бы он покрывал

;весь реально существующий код.

       mov cl,10011000b; права доступа сегмента кода (P=1,DPL=00b,S=1, тип =100b, A=0)

       call set_descriptor;Конструируем дескриптор кода

       lea  dx,Stack_seg_start ;EDX=DX=начало стека (см. метку)

       add eax,edx; EAX уже содержит адрес начала сегмента кода, сегмент стека

                                    ;начнётся с последней метки программы Stack_seg_start.

       mov dx,1024; Предел стека. Также любой, лишь бы его было достаточно.

       mov cl,10010110b; Права доступа сегмента стека (P=1,DPL=00b,S=1, тип=011b,A=0)

       call set_descriptor       ; Конструируем дескриптор стека.            

       xor  eax,eax; EAX = 0

       mov ax,ds

       shl  eax,4; EAX = физический адрес начала сегмента данных.

       mov dx,0ffffh

       mov cl,10010010b

       call set_descriptor       ; Конструируем дескриптор данных.

       mov eax,0b8000h; Физический адрес начала сегмента видеопамяти для цветного

                                             ;текстового режима 80 символов, 25 строк

       mov edx,4000; Размер сегмента видеопамяти (80*25*2=4000).

       mov cl,10010010b; Права доступа - как сегмент данных

       call set_descriptor; Конструируем дескриптор сегмента видеопамяти.

; Готовим дополнительные дескрипторы для возврата в R-Mode:

       xor  eax,eax

       push cs

       pop ax

       shl  eax,4 ; EAX = физический адрес сегмента кода (и всех остальных сегментов,

                                ;т.к. это .com-программа)

       mov edx,0ffffh

       mov cl,10011010b ; P=1, DPL=00b, S=1, Тип=101b, A=0

       call set_descriptor       ; R_Mode_Code

       mov cl,10010010b ; P=1, DPL=00b, S=1, Тип=001b, A=0

       call set_descriptor       ; R_Mode_Data

; Устанавливаем GDTR:

       xor  eax,eax; EAX = 0

       mov edx,eax; EDX = 0

       mov ax,ds

       shl  eax,4; EAX = физический адрес начала сегмента данных.

       lea  dx,GDT

       add eax,edx; EAX = физический адрес GDT

       mov GDT_adr,eax; Записываем его в поле адреса образа GDTR.

       mov dx,55          ; Предел GDT = 8 * (1 + 6) - 1

       mov GDT_lim,dx; Записываем его в поле предела образа GDTR.

; запрет маскируемых прерываний:

       cli   ; Запрещаем прерывания. Для того, чтобы прерывания работали в

;защищённом режиме их нужно специально определять, здесь это не делается.

; запрет немаскируемых прерываний(которые не запрещаются cli):

       in    AL,70h

       or   AL,80h

       out  70h,AL

       lgdt GDTR; Загружаем образ GDTR в сам регистр GDTR.

       mov R_Mode_SP,sp      ; сохраняем указатель на стек

; Переходим в защищённый режим:

       mov eax,cr0

       or   al,1

       mov cr0,eax

; Процессор в защищённом режиме                               

       db   0eah           ; Этими пятью байтами кодируется

       dw  P_Mode_entry; Команда far jmp Code_selector:P_Mode_entry.

       dw  Code_selector

;----------------------------------------------------

P_Mode_entry:

; В CS находится уже не сегментный адрес сегмента кода, а ;селектор его дескриптора.

; Загружаем сегментные регистры. Для работы программы на любом 32-разр процессоре.

       mov ax,Screen_selector

       mov es,ax

       mov ax,Data_selector

       mov ds,ax

       mov ax,Stack_selector

       mov ss,ax

       mov sp,0

; выводим ZS-строку о входе в P-Mode:

       lea  bx,Start_P_Mode_ZS

       mov di,480 ; Выводим ZS-строку со смещения 480 в видеопамяти (оно

;соответствует началу 3-й строки на экране в текстовом режиме).

       call putzs ; вызов функции

; Работа программы в защищённом режиме (здесь - только вывод строки):

       lea  bx,P_Mode_ZS

       add di,160

       call putzs; печатаем

; Возвращаемся в режим реальных адресов. Для этого Запретить прерывания (CLI).

;Они были запрещены при входе в P-mode. Передать управление в читаемый сегмент

;кода, имеющий предел в 64Кб, сбросить очередь предвыборки и загрузить CSреальным

;сегментнымадресом

       db   0eah ;Команда far jmp R_Mode_Code:Pre_R_Mode_entry.

       dw  Pre_R_Mode_entry

       dw  R_Mode_Code

Pre_R_Mode_entry:

;Загрузить в SS,DS,ES,FS и GS селекторы дескрипторов,имеющих

; следующие параметры:

; 1) Предел = 64 Кб (FFFFh)

; 2) Байтная гранулярность (G = 0)

; 3) Расширяется вверх (E = 0)

; 4) Записываемый (W = 1)

; 5) Присутствующий (P = 1)

; 6) Базовый адрес = любое значение

       mov ax,R_Mode_Data  ;Селектор R_Mode_Data-"один для всех".

       mov ss,ax

       mov ds,ax

       mov es,ax

       mov fs,ax

       mov gs,ax

; Сбросить флаг PE в CR0.

       mov eax,cr0       ; чтение cr0

       and al,0feh ; FEh = 1111'1110b, сброс бита 0

       mov cr0,eax

;Выполнить farjump на программу режима реальных адресов.

                   db   0eah

R_Mode_offset     dw  ?; Значения R_Mode_offset и R_Mode_segment

R_Mode_segment dw  ?; сюда записаны перед входом в

                                          ; защищённый режим (в начале программы).

R_Mode_entry:

; Загрузить в регистры SS, DS, ES, FS и GS необходимые значения

; (восстанавливаем сохранённые значения):

       mov ss,R_Mode_SS

       mov ds,R_Mode_DS

       mov es,R_Mode_ES

       mov fs,R_Mode_FS

       mov gs,R_Mode_GS

mov sp,R_Mode_SP; Восстанавливаем указатель стека перед разрешением прерываний.

       sti; Разрешить прерывания (STI).

; разрешить NMI

in    al,70h

and   al,07Fh

out   70h,al

; подождать нажатия любой клавиши

mov   ah,0

int   16h

; Выводим ZS-строку "Back to real address mode..."

lea  bx,R_Mode_ZS

       mov ax,0b800h

       mov es,ax

       mov di,800

       call putzs ; Функция putzs универсальна и работает в обоих режимах.

       int   20h ; Конец программы (выход в MS-DOS).

set_descriptor       proc near

; Создаётдескриптор.

; DS:BX = дескриптор в GDT

; EAX = адрес сегмента

; EDX = предел сегмента

; CL = байт прав доступа (access_rights)

       push eax

       push ecx ; Регистры EAX и ECX будем использовать.

       push cx   ; Временно сохраняем значение access_rights.

       mov cx,ax ; Копируем младшую часть адреса в CX,

       shl  ecx,16 ; и сдвигаем её в старшую часть ECX.

       mov cx,dx ; Копируем младшую часть предела в CX. Теперь ECX содержит

                                  ;младшую часть дескриптора (т.е. первые 4 байта ).

mov [ bx ],ecx ; Записываем младшую половину дескриптора в GDT.

       shr  eax,16 ; EAX хранит адрес сегмента, младшую часть которого мы уже

                          ;использовали, теперь будем работать со старшей, для чего сдвигаем её в

                   ; младшую часть EAX, т.е. в AX.

       mov cl,ah; Биты адреса с 24 по 31

       shl  ecx,24; сдвигаем в старший байт ECX,

       mov cl,al; а биты адреса с 16 по 23 - в младший байт.

       pop ax   ; Возвращаем из стека в AX значение access_rights

       mov ch,al; и помещаем его во второй (из четырёх) байт ECX. дескриптор готов.

;Старшую часть предела и биты GDXU не устанавливаем.они будут равны нулю.

       mov [ bx + 4 ],ecx ; Дописываем в GDT вторую половину дескриптора.

       add bx,8; Переводим указатель в GDT для работы со следующим дескриптором

       pop ecx

       pop eax

       ret

endp set_descriptor

;===функция=======================

putzs proc near

; DS:BX = ZS ; ZS = Zero-String - строка, оканчивающаясянулевым (00h) байтом.

; ES:DI = позиция вывода ; ES описывает сегмент видеопамяти, DI - смещение в нём.

       push ax

       push bx

       push es

       push di

mov ah,1bh ; В AH будет атрибут вывода - светло-циановые символы на синем фоне.

putzs_1:

       mov al,[ bx ]      ; Читаем байт из ZS-строки.

       inc  bx   ; Переводим указатель на следующий байт.

       cmp al,0 ; Если байт равен 0, то получили ZS и

       je    putzs_end; переходим в конец процедуры.

       mov es:[ di ],ax; Иначе - записываем символ вместе с атрибутом в видеопамять по

                                        ;указанному смещению - цветной символ появится на экране.

       add di,2; Переводим указатель в видеопамяти на позицию следующего символа.

       jmp putzs_1; Повторяем процедуру для следующего байта из ZS-строки, цикл

putzs_end:

       pop di

       pop es

       pop bx

       pop ax

       ret

endp putzs

;------------------------------------------------------------

; ZS-строка для вывода при входе в P-Mode:

Start_P_Mode_ZS: db   "Leaving Real Mode...",0

; ZS-строка для вывода при работе в P-Mode:

P_Mode_ZS: db   "<Family> working in 32-bit PMode...",0

; ZS-строка для вывода в R-Mode:

R_Mode_ZS: db   "Back to Real Mode...",0

;-----------------------------------------------------

; Для сохранения регистров до перехода в P-Mode:

R_Mode_SP dw  ?

R_Mode_SS dw  ?

R_Mode_DS dw  ?

R_Mode_ES dw  ?

R_Mode_FS dw  ?

R_Mode_GS dw  ?

; Образ регистра GDTR:

GDTR label fword

GDT_lim                dw  ?

GDT_adr                dd   ?

GDT:

       dd   ?,?  ; 0-йдескриптор

       dd   ?,?  ; 1-йдескриптор (кода)

       dd   ?,?  ; 2-й дескриптор (стека)

       dd   ?,?  ; 3-й дескриптор (данных)

       dd   ?,?  ; 4-й дескриптор (видеопамяти)

       dd   ?,?  ; 5-й дескриптор (код для перехода в R-Mode)

       dd   ?,?;6-й дескриптор(стек и данные для перехода в R-Mode)

       db   1024 dup (?) ; Зарезервировано для стека.

Stack_seg_start:; Последн метка программы-отсюда будет расти стек.

main          endp

       pmode ends

       end start

Порядок выполнения работы

1) Исследовать и понять приведенный код.

2) Скомпилировать и запустить исполнимый .comфайл из реального режима. Это можно осуществить или загрузившись с флеш-диска или из виртуальной машины и убедиться в ее работоспособности.

Для компиляции программы и создания .com использовать tasm, tlink(можно с помощью BAT файла):

в формате DOSCOM: tasm /m<имя файла>.asm

tlink /t /3 /x<имяфайла>.obj

3) Изменить код, обеспечив вывод в защищенном режиме на экран своей фамилии. Повторить шаг 2).

4) Для изучения механизма выполнения 32-разрядного сложения и работы с отладчиком надо после возврата из защищенного режима вставить код, который прибавляет к номеру зачетки дату вашего рождения и результат записывает в переменную sum . Например,

mov eax,19980101h ; Первый 32-разрядный операнд

add eax,87654321h ; Второй 32-разрадный операнд

mov dword ptr sum,eax ; Запись результата в sum

5) Для отладки программы используется отладчик (TD.exe) фирмы Borland. Для отображения содержимого 32-разрядных регистров надо после запуска отладчика, выбрать опцию «ViewRegisters». В появившемся окне выбрать Registers. Затем необходимо вызвать локальное меню этого окна и нажавALT-F10, выбрать в меню пункт Registers 32 bit.

Это обеспечит вывод на экран содержимого полных 32-разрядных регистров EAX...ESP взамен 16-разрядных регистров AX...SP.

6) Установить точку останова после вычисления суммы и выполнить программу до точки останова. Результат продемонстрировать преподавателю.

7) Оформить и защитить отчет.

Содержание отчета

1. Текст программы переключения режимов работы процессора.

2. Скрин-шот работы программы


Дата добавления: 2018-04-05; просмотров: 475; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!