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


Пример программы - часть 2


; может быть, это Windows 95 делает вид, что РЕ = 0? no_V86: mov ax,1600h ; Функция 1600h int 2Fh ; прерывания мультиплексора, test al,al ; если AL = 0, jz no_windows ; Windows не запущена ; сообщить и выйти, если мы под Windows mov dx,offset win_msg jmp short err_exit

; итак, мы точно находимся в реальном режиме no_windows: ; если мы собираемся работать с 32-битной памятью, стоит открыть А20 in al,92h or al,2 out 92h,al ; вычислить линейный адрес метки PM_entry xor еах,еах mov ax,PM_seg ; АХ - сегментный адрес PM_seg shl eax,4 ; ЕАХ - линейный адрес PM_seg add eax,offset PM_entry ; EAX - линейный адрес PM_entry mov dword ptr pm_entry_off,eax ; сохранить его ; вычислить базу для GDT_16bitCS и GDT_16bitDS xor eax,eax mov ax,cs ; AX - сегментный адрес RM_seg shl eax,4 ; ЕАХ - линейный адрес RM_seg push eax mov word ptr GDT_16bitCS+2,ax ; биты 15 - 0 mov word ptr GDT_16bitDS+2,ax shr eax,16 mov byte ptr GDT_16bitCS+4,al ; и биты 23 - 16 mov byte ptr GDT_16bitDS+4,al ; вычислить абсолютный адрес метки GDT pop eax ; EAX - линейный адрес RM_seg add ax,offset GDI ; EAX - линейный адрес GDT mov dword ptr gdtr+2,eax ; записать его для GDTR ; загрузить таблицу глобальных дескрипторов lgdt fword ptr gdtr ; запретить прерывания cli ; запретить немаскируемое прерывание in al,70h or al,80h out 70h,al ; переключиться в защищенный режим mov eax,cr0 or al,1 mov cr0,eax ; загрузить новый селектор в регистр CS db 66h ; префикс изменения разрядности операнда db 0EAh ; код команды дальнего jmp pm_entry_off dd ? ; 32-битное смещение dw SEL_flatCS ; селектор RM_return: ; сюда передается управление при выходе из защищенного режима ; переключиться в реальный режим mov еах,cr0 and al,0FEh mov cr0,eax ; сбросить очередь предвыборки и загрузить CS реальным сегментным адресом db 0EAh ; код дальнего jmp dw $+4 ; адрес следующей команды dw RM_seg ; сегментный адрес RM_seg ; разрешить NMI in al,70h and al,07Fh out 70h,al ; разрешить другие прерывания sti ; подождать нажатия любой клавиши mov ah,0 int 16h ; выйти из программы mov ah,4Ch int 21h ; текст сообщения с атрибутами, который мы будем выводить на экран message db 'Н',7,'е',7,'l',7,'l',7,'о',7,' ',7,'и',7,'з',7,' ',7 db '3',7,'2',7,'-',7,'б',7,'и',7,'т',7,'н',7,'о',7,'г',7 db 'о',7,' ',7,'Р',7,'М' message_l = $ - message ; длина в байтах rest_scr = (80*25*2-message_l)/4 ; длина оставшейся части экрана ; в двойных словах ; таблица глобальных дескрипторов GDT label byte ; нулевой дескриптор (обязательно должен быть на первом месте) db 8 dup(0) ; 4-гигабайтный код, DPL = 00: GDT_flatCS db 0FFh,0FFh,0,0,0,10011010b,11001111b,0 ; 4-гигабайтные данные, DPL = 00: GDT_flatDS db 0FFh,0FFh,0,0,0,10010010b,11001111b,0 ; 64-килобайтный код, DPL = 00: GDT_16bitCS db 0FFh,0FFh,0,0,0,10011010b,0,0 ; 64-килобайтные данные, DPL = 00: GDT_16bitDS db 0FFh,0FFh,0,0,0,10010010b,0,0 GDT_l = $ - GDT ; размер GDT




Начало  Назад  Вперед