Mov CR0,EAX ;защита разрешена
; Безусловный дальний переход на метку SetPMode
; (очистить очередь команд и перезагрузить CS)
DB 0EAh
DW (offset SetPMode)
DW SYS_PROT_CS
SetPMode:
; Подготовить границы сегментов
Mov AX,SYS_REAL_SEG
Mov SS,AX
Mov DS,AX
Mov ES,AX
Mov FS,AX
; Снять ограничения с сегмента GS
Mov AX,SYS_MONDO_SEG
Mov GS,AX
; Вернуться в реальный режим
Mov EAX,CR0
And AL,11111110b ;сбросить бит PE
Mov CR0,EAX ;защита отключена
; Безусловный дальний переход на метку SetRMode
; (очистить очередь команд и перезагрузить CS)
DB 0EAh
DW (offset SetRMode)
Self_Mod_CS DW ?
SetRMode:
; Регистры стека и данных
; настроить на сегмент кода
Mov SS,BX
Mov DS,BX
; Обнулить дополнительные сегментные
; регистры данных (GS не трогать!)
Xor AX,AX
Mov ES,AX
Mov FS,AX
; Возврат в реальный режим,
; прерывания снова разрешены
In AL,CMOS_ADDR
And AL,07Fh
Or AL,CH
Out CMOS_ADDR,AL
Popf
Ret
ENDP SetLAddrModeForGS
;****************************************
;* Разрешить работу с памятью выше 1 Мб *
;****************************************
PROC Enable_A20 near
Call Wait8042BufferEmpty
Mov AL,0D1h ;команда управления линией A20
Out 64h,AL
Call Wait8042BufferEmpty
Mov AL,0DFh ;разрешить работу линии
Out 60h,AL
Call Wait8042BufferEmpty
Ret
ENDP Enable_A20
;***********************************************
;* ОЖИДАНИЕ ОЧИСТКИ ВХОДНОГО БУФЕРА I8042 *
;* При выходе из процедуры: *
;* флаг ZF установлен - нормальное завершение, *
;* флаг ZF сброшен - ошибка тайм-аута. *
;***********************************************
Proc Wait8042BufferEmpty near
Push CX
Mov CX,0FFFFh ;задать число циклов
@@kb: in AL,64h ;получить статус
Test AL,10b ;буфер i8042 свободен?
loopnz @@kb ;если нет, то цикл
Pop CX
; (если при выходе сброшен флаг ZF - ошибка)
Ret
Endp Wait8042BufferEmpty
ENDS
ВНИМАНИЕ! Как уже было сказано, после выхода из защищенного режима нельзя перезаписывать регистр GS, иначе будет полностью или частично стерта информация в соответствующем теневом регистре. В частности, нельзя выполнять операции сохранения/восстановления содержимого регистра при помощи команд работы со стеком push и pop. |
При использовании нестандартных режимов работы возникают определенные трудности в процессе отладки программ: стандартные программы-отладчики становятся неудобными. Во многих случаях, однако, достаточно использовать простую отладочную печать. В листинге 2.2 [1] приведена подпрограмма ShowRegs, отображающая на экране содержимое регистров общего назначения, сегментных регистров, регистра флагов и регистра CR0. Недостаток этого упрощенного примера заключается в том, что ShowRegs не сохраняет содержимое видеопамяти. Однако при использовании линейной адресации программу не трудно усовершенствовать, если есть достаточный запас оперативной памяти: в текстовом режиме для сохранения одной страницы нужно менее 4 Кбайт, а в графическом режиме TrueColor32 с разрешением 1920x1280 требуется уже 9,5 Мбайт.
Листинг 2.2 – Отладочная подпрограмма, предназначенная для отображения на экран содержимого регистров процессора