Переключение между 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-разрядных регистров надо после запуска отладчика, выбрать опцию «View→Registers». В появившемся окне выбрать Registers. Затем необходимо вызвать локальное меню этого окна и нажавALT-F10, выбрать в меню пункт Registers 32 bit.
Это обеспечит вывод на экран содержимого полных 32-разрядных регистров EAX...ESP взамен 16-разрядных регистров AX...SP.
6) Установить точку останова после вычисления суммы и выполнить программу до точки останова. Результат продемонстрировать преподавателю.
7) Оформить и защитить отчет.
Содержание отчета
1. Текст программы переключения режимов работы процессора.
2. Скрин-шот работы программы
Дата добавления: 2018-04-05; просмотров: 475; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!