Глава 26. Программирование в защищенном режиме.

Без надобности носимый на­брюшник - вреден.

Козьма Прутков.

Данная глава является логическим продолжением главы 5. В главе 5 явно не гово­рится о том, как программировать в защищенном режиме, хотя и дается представле­ние о нем. Программы данной главы рассчитаны на MASM.EXE версии 5.0. При ис­пользовании MASM.EXE более высоких версий могут возникнуть проблемы следую­щего порядка:

1. Команда типа MOVAX,CRO будет давать ошибку, ее следует поменять на MOV EAX,CRO.

2. Команда вида LIDT QWORD МЕТ 1 также не пройдет. Следует поменять ее на LIDT FWORD MET EFWORD- шестибайтовая структура. Соответственно для резер­вирования такой структуры можно использовать DF.

Говоря о защищенном режиме, имейте в виду, что мы уже работали в нем с про­граммами предыдущей главы. Однако в Windows все управление брала на себя опера­ционная система. Здесь нам придется писать программы, берущие всю ответствен­ность на себя. Фактически написать которая самостоятельно работает в защищенном режиме, это написать маленькую операционную систему.

I.

Прежде всего вспомним некоторые положения, рассмотренные в главе 5.

1. В защищенном режиме физический адрес формируется из селектора и смеще­ния. Селектор содержится в сегментном регистре и представляет собой не сегмент­ный адрес, как в реальном режиме, а индекс-указатель на дескриптор в дескриптор-ной таблице. Дескриптор представляет собой описатель сегмента - физический адрес, размер сегмента, байт-описатель сегмента (байт доступа).

2. Система имеет одну глобальную дескрипторную таблицу и может иметь не­сколько локальныхдескрипторныхтаблиц. В случае одной задачи локальные деск-рипторныетаблицы не используются.

3. Содержимое сегментного регистра в защищенном режиме имеет следующую структуру: первые три бита носят служебный характер (см. главу 5), оставшиеся 13 бит представляют собой индекс, другими словами номер дескриптора в дескрипторной таб­лице. Бит2определяет,какаядескрипторнаятаблицаиспользуется(0-глобальная).

4. То, что под индекс, указывающий на дескриптор, отведены старшие 13 бит, да­леко не случайный факт. Дело втом, что длинадескриптора 8 байт. Вначале идет нуле­вой, неиспользуемый дескриптор. Если DESC0- метка начала нулевого дескриптора, DESC - метка начала другого дескриптора, то разность DESC-DESC0 - кратна 8 и пред­ставляет собой какраз индекс дескриптора DESC, помещенный в старшие 13 бит. Этот факт значительно упрощает работу с дескрипторами в программе.

5. Мы привыкли оперировать даухкомпонентным адресом, состоящим из сегмен­та и смещения. Покажем, как перевести его в физический адрес, который должен быть помещен в дескриптор. Пусть сегментный адрес помещен в АХ, а смещение - в ВХ. Получим трехбайтный (24-битный) физический адрес в БЬ:АХ. Следующие команды справляются с указанной задачей.

MOV

SHL АХ,4 SHR DL,4 ADD АХ, ВХ ADC DL,0

б. В защищенном режиме программные прерывания перестают работать. Поэтому нам придется писать собственные процедуры работы с внешними устройствами. Для реализации аппаратных прерываний необходимо создавать свою таблицу дескрипто­ров прерываний. Если программа не собирается долго находиться в защищенном ре­жиме, то простейший выход из этого положения - это просто запретить все прерыва­ния на время работы в защищенном режиме.

У. В дальнейшем Вам понадобятся сведения о CMOS - памяти, питающейся от независимого источника (см. главу 23). При запуске компьютера содержимое CMOS анализируется процедурами BIOS, которые извлекают оттуда информацию о конфи­гурации системы, а также текущую дату и время. Доступ к CMOS осуществляется через порты У0Н и

Чтение из CMOS: MOV AL,XXH

OUT 70Н,AL ;выбор номер ячейки CMOS JMP  $+2       ; задержка

IN    AL,71H   ;ввод байта из CMOS

Запись в CMOS:

MOV AL,XXH

OUT 70H,AL   ;выбор номер ячейки CMOS

JMP $+2        ; задержка

MOV AL, YYH   ;байт для  ввода  в CMOS

OUT 71H,AL

Порт У0Н служит не только для индексирования ячеек CMOS, но и для разре­шения или запрещения NMI (немаскируемого прерывания). Если бит У равен 0, то

NMI разрешается, в противном случае запрещается. Тут есть один интересный момент. Управление NMI и индексацию можно совместить в одной команде. Если в AL лежит байт с нулевым У-м битом, то OUT 70H,AL не только индексирует ячейку CMOS, но и размаскирует NMI. Адреса ячеек CMOS находятся в проме­жутке 00H-3FH. Если адрес ячейки больше 3FH, то автоматически учитывается

только младший байт.

8. Ячейка с номером FH CMOS называется байтом состояния перезагрузки. Этот байт считывается после сброса центрального процессора, чтобы определить, не был ли сброс вызван для вывода из защищенного режима. Если содержимое этого байта равно 5, то осуществляется выполнения команды

JMP FAR PTR [0:467Н]

в   защищенном режиме процессора

.286Р

доступа

; lQQQQQQQB  -  сегмент есть в памяти . ;00011000В  -  сегмент кода

- сегмент данных QQQQQlQQB   -   сегмент расширяется вниз

/QQQQQlQQB - согласованный сегмент

- разрешена запись данных

DATA_AC     EQU 10010010В

/сегмент кода

CODE_AC     EQU lQQlllQQB

/сегмент стека

STACK_AC   EQU lQQlQllQB

DATA SEGMENT

BEG_DATA = $

для вывода MSG        DB Я в защищенном

MSGl     DB Я снова в реальном

/данные для вывода на экран

COLUMNS   DB  ? /количество   столбцов   на экране

ROWS        DB ? /количество  строк на экране

SEL_BUF  DW ?        '   /селектор видеобуфера SEGBUF   DW ? ; сегментный  адрес видеобуфера

хранятся  сегментные регистры _SS DW ?

_DS DW ?

_ES DW ?

SP DW

дескрипторная таблица

/нулевой дескриптор

GDT0 DQ 0

/дескриптор для GDT

GDT_GDT    DQ О

/дескриптор для  сегмента данных GDT DS    DQ Qдля сегмента кода GDT_CS     DQ О

для  сегмента стека

GDT_SS    DQ О

для  видеопамяти цветного дисплея

GDT_CRT   DQ О

для  видеопамяти монохромного дисплея GDT_MDA   DQ О

GDT_SIZE  =   $-GDTO       /размер  глобальной дескрипторной таблицы

DSEG_SIZE = $-BEG_DATA /размер сегмента данных DATA ENDS

стека

ST1   SEGMENT  STACK 'STACK' DB   lQQ DUP(?)

STl ENDS

кода

CODE SEGMENT

ASSUME CSrCODE,   DS:DATA, SS:ST1

BEG:

сегмент данных MOV AX,DATA MOV DS,AX

/определяем базовый адрес видеопамяти

CALL WHAT_CRT

/подготовка перехода в защищенный режим CALL INI_PROT

/•переключение в   защищенный режим

CALL SET_PROT

/стираем экран       защищенном режиме MOV   АН,77Н

CALL CLS

сообщения в   защищенном режиме ;координаты

' MOV ВХ,0 /координата Y

MOV АХ,15 /координата X

;адрес выводимой строки MOV SI,OFFSET MSG MOV АН,41Н /атрибут

CALL WRITE ;пауза

CALL PAUSE

/вернуться в реальный режим

CALL SET REALв реальном режиме

;стираем экран MOV АН, 7

CALL CLS ;вывод сообщения ; координаты

mov  вх, 0

MOV АХ,15 ;адрес выводимой

MOV SI,OFFSET MSG1

MOV АН,13     ;атрибут

CALL WRITE ;пауза

CALL PAUSE ;конец работы программы

MOV АН,4СН

int 21h ;раздел процедур ; процедура задержки PAUSE PROC

PUSH СХ MOV СХ,50

в  реальном режиме

;координата y

X

строки

pl:

PL1:

PUSH СХ MOV

LOOP PL1 POP CX

LOOP PL

POP CX RETN PAUSE ENDP

параметров

PROC

MOV MOV MOV MOV MOV

INC BL

MOV ROWS,BL

MOV BX,ES:[63H]

CMP

JNE  NO COLOR для видеобуфера

;цветной адаптер

MOV SEL_BUF, (GDT_CRT-GDTO)

MOV   SEG_BUF, 0B800H

MOV ES,SEG_BUF

JMP  SHORT EXIT NO_COLOR: /адаптер MDA

MOV   SEL_BUF, (GDT__MDA-GDTO)

MOV   SEG_BUF, 0В000Н

MOV ES,SEG_BUF

EXIT:

RETN WHAT_CRT ENDP ;процедура очистки экрана

;в ES находится либо селектор,   либо сегмент ;в АН - атрибут CLS PROC

MOV СХ,2000

MOV   AL, 32

XOR DI,DI

L2:

STOSW

LOOP L2 RETN CLS ENDP

,-процедура  выводит сообщение

; в ES либо  селектор экрана,   либо адрес сегмента

;АХ,ВХ - X,Y

;SI -  адрес строки

;АН - атрибут

WRITE PROC

/расчет смещения в видеопамяти

PUSH AX

MOV  DL,COLUMNS

MUL DL ADD АХ/ВХ SHL AX/l MOV DI,AX

POP AX

LOl:

LODSB CMP AL,0 JZ EN

STOSW

JMP SHORT L01

EN:

RETN

WRITE ENDP

;процедура инициализации  защищенного режима INI_PROT PROC ;заполнение GDT

;-вычисление   физического адреса-

MOV АХ,DATA MOV  DL, АН SHR  DL, 4 SHL AX, 4 MOV SI,AX MOV DI,DX

-заполнение   дескриптора GDT-

ADD AX,OFFSET GDTO

ADC DL,0

MOV BX,OFFSET GDT_GDT

MOV WORD   PTR    [BX] ,GDT_SIZE-1

MOV [BX+2],AX

MOV [BX+4],DL

MOV BYTE   PTR    [BX+5],DATA_AC

;-заполнение  дескриптора для  сегмента данных-

MOV BX, OFFSET GDT_DS MOV AX,SI

MOV DX,DI

MOV WORD   PTR    [BX] , DSEG_SIZE-1 MOV [BX+2],AX

MOV    [BX+4],DL

MOV BYTE   PTR    [BX+5] , DATA__AC

;-заполнение  дескриптора для  сегмента кода--

MOV BX,OFFSET GDT_CS MOV AX,CS MOV DL,AH SHR DL,4 SHL AX,4

MOV WORD   PTR    [BX] ,CSEG_SIZE-1 MOV [BX+2],AX MOV [BX+4],DL

MOV BYTE   PTR   [BX+5] ,CODE_AC

;-заполнение  дескриптора  для  сегмента стека-

MOV BX,OFFSET GDT_SS MOV AX,SS MOV DL,AH SHR DL, 4

SHL AX,4

MOV WORD   PTR    [BX], 400-1 MOV [BX+2],AX

MOV

MOV BYTE   PTR    [BX+5],DATA_AC

,*-заполнение  дескриптора для  видеопамяти CRT-

MOV BX,OFFSET GDT_CRT

MOV WORD  PTR   [BX], 3999

MOV WORD   PTR [BX+2],8000H

MOV BYTE   PTR [BX+4],OBH

MOV BYTE PTR [BX+5] , DATA_AC ;-заполнение дескриптора для  видеопамяти MDA-

MOV BX,OFFSET GDT_MDA

MOV WORD PTR   [BX], 3999

MOV BYTE   PTR [BX+4],0BH

MOV BYTE PTR [BX+5],DATA_AC ;-адрес   возврата  из   защищенного режима--

PUSH DS

MOV    AX,4ОН

MOV    DS, AX

MOV word ptr DS: [67H],OFFSET SHUT_DOWN_RETURN MOV    DS:[69H],CS

POP DS

;-маскируем  все прерывания-

;записываем в ячейку OFH CMOS код 5 ; чтобы обеспечить   возврат  после   сброса процессора маскируем NMI

CLI

MOV AL,8FH OUT   7 0H,AL

JMP NEXT1 ; небольшая задержка

NEXT1:

MOV AL,5 OUT 71H,AL

RETN

INI_PROT ENDP

/процедура переключения   в   защищенный режим SET_PROT PROC

MOV _SS,SS

MOV _ES,ES /загружаем регистр GDTR

LGDT GDT_GDT устанавливаем   защищенный режим

MOV   AX, 1

LMSW AX

19-4072,---JMP FAR FLUSH,  для сбрасывания очереди команд

DB ОЕАН

DW      OFFSET FLUSH

DW        <GDT_CS-GDTO)

FLUSH:

;загрузка селекторов

MOV    AX, (GDT_DS-GDTO) MOV    DS, AX MOV AX,SEL_BUF MOV ES,AX

MOV    AX,(GDT_SS-GDTO) MOV SS,AX

RETN SET_PROT ENDP

/процедура возврата  в реальный режим SET_REAL PROC

/запомнить  содержимое  регистра стека

MOV _SP,SP ;сброс процессора

MOV AL,0FEH

OUT 64H,AL

/ожидание возврата  по метке SHUT_DOWN_RETURN _WAIT:

JMP _WAIT / —теперь мы в реальном режиме—

возврата SHUT_DOWN_RETURN:

/восстанавливаем значения  всех сегментных регистров MOV АХ,DATA MOV DS,AX

MOV SS,_SS MOV SP,_SP MOV ES,_ES /разрешаем все прерывания прерывания MOV    AX,ODH OUT 70H,AL

/маскируемые прерывания  на уровне   контроллера прерываний XOR    AL,AL

OUT     21H,AL ■

/разрешаем маскируемые  прерывания  на уровне микропроцессора STI RETN SET REAL ENDP

CSEGSIZE = $-BEG

code ends

end beg

Вывод в защищенном режиме строки и очистка экрана.

На Рис. 20.1 представлена программа, работающая в защищенном режиме. Про-граммадостаточно хорошо прокомментирована, поэтому рассмотрим лишь несколько

замечаний.

1. Программа переходит в защищенный режим. Стирает экран и печатает строку. Затем происходит возврат в реальный режим и снова печать строки.

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

Обращаю Ваше внимание, что процедуры печати строки и очистки экрана одни и те же в реальном и защищенном режиме. Но если в реальном режиме в сегментных регистрах должны находиться адреса сегментов, в защищенном режиме в сегментных регистрах должны содержаться индексы, указывающие на дескрипторы сегментов.

4. Как отмечалось раньше, если в защищенном режиме работает всего одна про­грамма, нет смысла создавать локальную дескрипторную таблицу. Поэтому моя про­грамма использует лишь глобальную дескрипторную таблицу.

Одна из преимуществ защищенного режима - возможность использовать всю па­мять компьютера. На Рис. 20.2 представлена программа, аналогичная предыдущей, но выполняющая еще одну функцию. Она копирует экранную область в память за 1Мб. Чтобы использовать эту память, предварительно следует открыть адресную линию А20, что делает процедура ENABLE. Заметим, что аналогичную операцию делала программа на Рис. 5.2из главы 5. Однако там было использовано для этой цели преры­вание 15Н.

в защищенном режиме процессора

.286Р

доступа

- сегмент есть  в памяти

- сегмент кода

- сегмент данных

;00000100В -  сегмент расширяется вниз ; 00000100В -   согласованный сегмент

- разрешена запись данных

DATA_AC     EQU 10010010В кода

CODE_AC   EQU lQQlllQQB

стека

STACK_AC EQU lQQlQllQB DATA SEGMENT

BEG DATA  = $

для вывода

MSG DB    'HELLO! Я  в   защищенном режиме!1,О

MSGl        DB Я снова в реальном

DB экрана отправлена в

для  вывода  на экран COLUMNS DB ? /количество столбцов на экране

ROWS        DB ? /количество строк на экране

SEL_BUF  DW ? /селектор видеобуфера

'SEG_BUF DW ? ;сегментный адрес видеобуфера

хранятся  сегментные регистры __SS DW ?

]_DS DW ?

]_ES DW ?

_SP DW ?

дескрипторная таблица дескриптор GOTO DQ 0

для GDT GDT_GDT   DQ О

для  сегмента данных

GDT_DS    DQ О

для   сегмента кода

GDT_CS    DQ О

для  сегмента стека

GDT_SS    DQ О

для   видеопамяти цветного дисплея

GDT_CRT   DQ О

дескриптор для  видеопамяти монохромного дисплея

GDT_MDA  DQ О

/дескриптор расширенной памяти,   куда будем копировать экран

GDT_MEM   DQ О

'GDT_SIZE = $-GDTO /размер глобальной дескрипторной таблицы DSEG_SIZE   =   $-BEG_DATA   /размер сегмента данных

DATA ENDS

стека

ST1   SEGMENT   STACK 'STACK' DB   100 DUP(?)

STl ENDS

кода

CODE SEGMENT

ASSUME CS:CODE,   DS:DATA, SS:ST1

BEG:

сегмент данных MOV AX,DATA MOV DS,AX

5S1

/определяем базовый  адрес видеопамяти

CALL WHAT_CRT /подготовка перехода  в  защищенный режим

CALL INI_PROT /переключение в   защищенный режим

CALL SET_PROT /стираем экран  в  защищенном режиме

MOV АН,77Н

CALL CLS сообщения  в  защищенном режиме / координаты

MOV ВХ,0      /координата Y

MOV АХ,15    /координата X /адрес выводимой строки

MOV  SI,OFFSET MSG

MOV АН,41Н /атрибут

CALL WRITE /пауза

CALL PAUSE /копируем экран в память

CALL TO_MEM

экран MOV АН,39Н CALL CLS

сообщения  в   защищенном режиме MOV ВХ,0      /координата Y MOV АХ,15    /координата X MOV SI,OFFSET MSG2 MOV АН,71Н /атрибут

CALL WRITE /пауза

CALL PAUSE

/копируем экран из памяти

CALL FROM_MEM /пауза

CALL

/вернуться в реальный режим

CALL SET_REAL

экран в реальном режиме MOV АН,7

CALL CLS

/вывод сообщения  в реальном режиме координаты MOV ВХ,0      /координата Y MOV АХ,15     /координата X

; адрес выводимой строки MOV SI, OFFSET MSG1 MOV АН, 13   ; атрибут

CALL WRITE

;пауза

CALL PAUSE ; конец работы программы MOV АН,4СН INT 21H

/раздел  процедур  процедура задержки

;для быстрого компьютера следует увеличить значение, засылаемое в СХ PAUSE PROC

PUSH

CX

 

MOV

CX,

50

PUSH

CX

 

MOV

CX,

OFFFFH

LOOP

PL1

 

POP

CX

 

LOOP

PL

 

POP

CX

 

RETN

 

 

PAUSE ENDP

/определение параметров для видеобуфера WHAT_CRT PROC

MOV AX,4OH

MOV ES,AX

MOV BX,ES: [4AH]

MOV COLUMNS,BL

MOVBL,ES: [84H]

INC BL

MOV ROWS/BL

MOVBX,ES: [63H]

CMP BX,3D4H

JNE NOCOLOR

MOV SEL_BUF, (GDT__CRT-GDT0)

MOV SEG_BUF,0B800H

MOV ES,SEG_BUF

JMP   SHORT EXIT NOCOLOR: ; адаптер MDA

MOV SEL_BUF,(GDT_MDA-GDT0)

MOV SEG_BUF,0В000Н

MOV ES,SEG BUF

EXIT:

RETN

WHAT_CRT ENDP

очистки экрана ;в ES находится либо селектор,   либо сегмент ; в АН - атрибут

CLS PROC

MOV СХ,2000 MOV   AL, 32 XOR DI,DI

STOSW LOOP L2 RETN CLS ENDP

/процедура выводит сообщение

; в ES либо селектор экрана,   либо сегмент

;АХ,ВХ X,Y

;SI -  адрес строки

;АН - атрибут

WRITE PROC

в видеопамяти

PUSH AX

MOV DL,COLUMNS

MUL DL

ADD АХ,ВХ ■ SHL АХ,1 MOV DI,AX

POP AX

L01:

LODSB

CMP AL,О

JZ EN

STOSW

JMP SHORT LOl

EN:

RETN WRITE ENDP

инициализации   защищенного режима

INI_PROT PROC

заполнение

MOV

MOV DL, AH SHR DL,4

SHL AX, 4 MOV SI, AX MOV DI, DX

ADD AX,OFFSET GOTO ADC DL,0

MOV BX,OFFSET GDT_GDT

MOV WORD  PTR   [BX] , GDT_SIZE-1

MOV [BX+2],AX

MOV [BX+4],DL

MOV BYTE   PTR    [BX+5],DATA_AC

MOV GDT_DS

MOV AX,SI

MOV DX,DI

MOV WORD  PTR   [BX] , DSEG_SIZE-1 MOV [BX+2],AX MOV [BX+4],DL

MOV BYTE  PTR    [BX+5] , DATA_AC

MOV GDT_CS

MOV AX,CS MOV DL,AH SHR  DL, 4 SHL AX,4

MOV WORD PTR [BX] , CSEG_SIZE-1 MOV [BX+2],AX

MOV [BX+4],DL

MOV BYTE   PTR   [BX+5] , CODE_AC

MOV GDT_SS

MOV AX,SS

MOV DL, AH

SHR DL, 4

SHL AX,4

MOV WORD  PTR    [BX], 400-1 MOV [BX+2],AX

MOV [BX+4],DL

MOV BYTE   PTR    [BX+5] , DATA AC

MOV BX,OFFSET GDT_CRT

MOV WORD  PTR [BX],3999

MOV WORD   PTR [BX+2],8000H

MOV BYTE   PTR [BX+4],0BH

MOV BYTE   PTR [BX+5] , DATA AC

MOV BX,OFFSET GDT_MDA ■ MOV WORD  PTR    [BX], 3999 MOV BYTE   PTR [BX+4],0BH MOV BYTE   PTR    [BX+5] , DATA_AC

;-дескриптор  области  озу для  копирования экрана--

MOV BX,OFFSET GDT_MEM

MOV WORD  PTR    [BX], 3999

MOV WORD  PTR   [BX+2], 0000H

MOV BYTE   PTR [BX+4],15H

MOV BYTE   PTR    [BX+5],DATA_AC ;-адрес   возврата  из   защищенного режима

PUSH DS

MOV AX,40H

MOV    DS, AX

MOV    word ptr  DS:   [67H],OFFSET SHUT_DOWN_RETURN MOV    DS: [69H],CS

POP DS

;---маскируем  все прерывания

;записываем в ячейку OFH CMOS код 5 /чтобы обеспечить   возврат  после  сброса процессора CLI

MOV AL,8FH OUT 70H,AL JMP NEXT1

NEXT1:

MOV AL,5 ' OUT 71H,AL

RETN INI_PROT ENDP

; процедура переключения   в   защищенный режим

SET_PROT PROC

MOV _SS,SS MOV _ES,ES

CALL ENABLE

регистр GDTR

LGDT GDT_GDT /устанавливаем защищенный режим MOV   AX, 1

LMSW AX

;-JMP FAR FLUSH,   для  сбрасывания  очереди команд

DB OEAH

DW    OFFSET FLUSH

DW        (GDT_CS-GDTO)

FLUSH:реальный режим

SHUT DOWN RETURN

; загрузка селекторов

MOV    AX,(GDT_DS-GDTO) MOV DS,AX MOV AX,SEL_BUF MOV ES,AX

MOV    AX,(GDT_SS-GDTO) MOV SS,AX RETN

SET_PROT ENDP ;процедура возврата в SET_REAL PROC

CALL DISABLE ; запомнить  содержимое регистра

MOV _SP,SP ;сброс процессора

MOV AL,OFEH OUT 64H,AL

возврата

_WAIT:

JMP _WAIT ; —теперь мы в реальном режиме-

возврата SHUT_DOWN_RETURN: ;восстанавливаем значения всех

MOV АХ,DATA

MOV DS,AX

MOV SS,_SS

MOV SP,_SP

MOV ES,_ES ./разрешаем все прерывания ;немаскируемые прерывания

MOV    АХ,0DH

OUT 70H,AL

прерывания

XOR    AL,AL

OUT 21H,AL

прерывания

STI

RETN SET_REAL ENDP

/процедура копирования экрана в память /в ES должен быть   загружен селектор экран ТО_МЕМ PROC

PUSH DS

MOV    АХ, (GDT MEM-GDTO)

сегментных регистров

на уровне   контроллера прерываний

на уровне микропроцессора

MOV XOR

XOR MOV

DS,AX SI, SI DI,DI CX,4000

LL1:

MOV    AL,ES:[SI]

MOV [DI],AL INC SI INC DI LOOP LL1 POP DS RETN TO_MEM ENDP

/процедура копирования из памяти на экран ;в ES  должен  быть   загружен  селектор экран FROM_MEM PROC PUSH DS

MOV    AX,(GDT_MEM-GDTO) MOV DS,AX XOR    SI,SI

■ XOR DI,DI MOV CX,4000

LL2 :

MOV    AL, [SI] " MOV    ES:[DI],AL

INC SI INC DI

LOOP LL2

POP DS RETN

FROM_MEM ENDP

/открыть адресную шину А20 /управление линией А2 0 осуществляется ENABLE PROC NEAR

через  порты клавиатуры

MOV

OUT 64H,AL

MOV AL,ODFH

OUT 60H,AL

RET

ENABLE ENDP

закрывает

DISABLE PROC NEAR

MOV AL,OD1H OUT 64H,AL

/команда управления линией А2 0 /порт состояния клавиатуры /открыть А20

порт

адресную шину А20

MOVAL,0DDH /закрыть А20

OUT 60H,AL

RET

DISABLE ENDP CSEG_SIZE = $-BEG

CODE ENDS

END BEG

Рис. 20.2. Программа, работающая в защищенном режиме: копирует содержимое экрана в адресное пространство за 1 Мб.

II.

До сих пор при входе в защищенный режим мы отключали все прерывания. Это наиболее простой способ написания программ. Сейчас предстоит рассмотреть вопрос об использовании прерываний в защищенном режиме.

Кратко суть проблемы. В защищенном режиме все прерывания делятся на обыч­ные прерывания и исключения (особые случаи). Программные прерывания иниции­руются командой INT. Аппаратные прерывания происходят при возникновении внеш­него события (нажатие клавиши и т.п.). При возникновении аппаратного прерывания флаг разрешения прерываний сбрасывается, и прерывания запрещаются. Исключения побуждаются ошибками, которые вызваны какими-либо командами. Типичной ошиб­кой является попытка записи в сегмент кода. При возникновении исключения преры­вания не запрещаются.

Обработка прерываний в защищенном режиме базируется на таблице прерыва­ний, которая содержит дескрипторы прерываний. Эти дескрипторы указывают на про­цедуру, которая должна выполниться при возникновении данного прерывания. Эти дескрипторы называются вентили. Положение таблицы определяется содержимым регистра IDTR. Загрузка регистра осуществляется командой LIDT.

Для обработки исключений зарезервирован 31 -й номер прерываний.

ООН ошибка при выполнении командыделения.

01Н прерывания для пошаговой работы.

02Н немаскируемое прерывание.

ОЗН прерывание по точке останова.

04Н генерируется командой INTO.

05Н генерируется командой BOUND, если проверяемое значение вышло за преде­лы заданного диапазона. 06Н недействительный код команды. 07Н отсутствие арифметического сопроцессора.

08Н двойная ошибка - если при обработке исключения возникло еще одно. 09Н превышение сегмента арифметическим сопроцессором. ОАН недействительный сегмент состояния задачи TSS.

ОВН отсутствие сегмента, который может находиться в данный момент на диске.

ОСН исключение при работе со стеком, например, переполнение. ODH исключение по защите памяти, например, попытка доступа к сегменту при недостаточности привилегий. ОЕН отказ страницы для процессоров 3 86 и выше. OFH зарезервировано. 1 ОН исключение сопроцессора. зарезервировано.

Заметим, что исключение можно вызвать и непосредственно командой INT. Перед тем как передать управление обработчику исключений, для многих зарезервирован­ных прерываний процессор помещает в стек 16-битный код ошибки. Ниже приведена структура кода ошибки.

О - устанавливается в том случае, если ошибка произошла по внешним относи­тельно выполняемой программы причинам.

1-2 - выбор локальной или глобальной таблицы - если бит 1 равен нулю, то бит 2 выбирает таблицу дескрипторов (0-глобальная, 1 -локальная).

индекс дескриптора, при обращении к которому произошла ошибка.

Кодошибкипомещаетсявстеквслучаеисключений: 08Н, ОАН, ОВН, ОСН, ODH.

Все исключения, кроме 01Н, 08Н, 09Н, ODH, 1 ОН, обладают свойством повторной запускаемости. Это означает следующее: для таких исключений (кроме 3 и 4) в стек включается адрес не следующей команды, а прерванной. Если выполнить команду IRET, то снова будет выполнена прерванная команда. Если, например, сегмент, к которому было обращение, окажется отсутствующим в памяти, то возникшее исключение мо­жет вызвать процедуру подкачки сегмента с диска и снова выполнить прерванную команду.

Если мы посмотрим на таблицу исключений, то заметим, что исключения 0-7 со­ответствуют прерываниям реального режима. Эти прерывания вызваны внутренним состоянием микропроцессора. Однако для обработки аппаратных прерываний IRQO-IRQ7 используются номера прерываний от08Н до OFH (см. главу 9). Но в защищен­ном режиме эти номера зарезервированы для исключений. Возникающая проблема решается перепрограммированием контроллера прерываний, что и делается в приве­денной ниже программе (процедура PROGJNT). Алгоритм перепрограммирования приведен в главе 9.

/работаем в защищенном режиме процессора .286Р

;байты доступа

;10000000В -   сегмент  есть   в памяти

;00011000В -  сегмент кода

;00010000В -   сегмент данных

; 00000100В -   сегмент расширяется вниз

;00000100В -  согласованный сегмент

;00000010В - разрешена запись

;00000110В -  вентиль прерывания

/00000111В -   вентиль исключения ;сегмент данных DATA_AC     EQU 10010010B ;сегмент кода CODE_AC     EQU 10011100B стека

STACK_AC   EQU 10010110B ;сегмент таблицы IDT

IDT_AC     EQU 10010010B

; байт доступа   вентиля прерывания

INT_AC     EQU 10000110B

доступа   вентиля исключения TRAP_AC    EQU 10000111В стека

ST1   SEGMENT  STACK 'STACK' DB   100 DUP(?)

ST1 ENDS

данных DATA SEGMENT BEG_DATA= $ ■

MSG DB ' Мы в защищенном режиме . 1 , _DL DB 0

для вывода

COLUMNS DB ?

? ? ■>

ROWS DB SEL_BUF DW

SEG_BUF DW

хранения _SS DW ? _ES DW ? _SP DW ?

;переменная для таймера TIME DW ?

дескрипторная дескриптор GDTO DQ О

/дескриптор для GDT GDT_GDT   DQ О /дескриптор для GDT_CS    DQ О

для

GDT_DS    DQ О /дескриптор для

GDT SS     DQ О

на экран

/количество столбцов на экране /количество строк на экране /селектор видеобуфера /сегментный адрес видеобуфера сегментных регистров

таблица

сегмента кода

сегмента данных

сегмента стекадля видеопамяти цветного дисплея

GDTCRT   DQ O

для  видеопамяти монохромного дисплея GDT_MDA    DQ О

;дескриптор таблицы прерываний

GDT_IDT   DQ О

GDT_SIZE = $-GDTO    /размер глобальной дескрипторной таблицы

;таблица прерываний

/вентили исключений IDT BEG=$

ЕХС_QQ

DQ

Q

ЕХС^І

DQ

Q

ЕХС Q2

DQ

Q

ЕХС_03

DQ

Q

ЕХС_04

DQ

Q

ЕХС Q5

DQ

Q

ЕХС_0б

DQ

Q

ЕХС_07

DQ

Q

ЕХС_08

DQ

Q

ЕХС_09

DQ

Q

ЕХС_ОА

DQ

Q

ЕХС_ОВ

DQ

Q

ЕХС_0С

DQ

Q

EXC_OD

DQ

Q

ЕХС_ОЕ

DQ

Q

EXC_OF

DQ

Q

ЕХС_1Q

DQ

Q

ЕХС_11

DQ

Q

ЕХС_12

DQ

Q

ЕХС l3

DQ

Q

ЕХС_14

DQ

Q

EXCJ.5

DQ

Q

ЕХС_16

DQ

Q

ЕХС_17

DQ

Q

ЕХС_18

DQ

Q

ЕХС_19

DQ

Q

ЕХС_1А

DQ

Q

ЕХС_1В

DQ

Q

ЕХС_1С

DQ

Q

EXC_1D

DQ

Q

ЕХС_1Е

DQ

Q

EXC_1F

DQ

Q

прерываний INT_2 0      DQ 0 ; таймер INT_21      DQ 0 ; клавиатура

DQ 0 DQ 0 DQ 0 DQ 0 DQ 0

DQ 0 DQ 0

DQ 0

DQ 0

DQ 0 DQ 0

DQ 0 DQ 0

DQ 0

IDT_SIZE=$-IDT_BEG       /размер таблицы прерываний

DSEG_SIZE=$-BEG_DATA  /размер   сегмента данных DATA ENDS ;сегмент кода CODE SEGMENT

ASSUME CS:CODE,   DS:DATA, SS:ST1

BEGIN:

MOV AX,DATA

MOV DS,AX

CALL WHAT_CRT /инициализировать дескрипторные таблицы

CALL INI_PROT ;выйти в   защищенный режим

CALL SET_PROT ; координаты

MOV ВХ, 0      /координата Y

MOVAX,15     /координата X /адрес выводимой строки

MOV SI,OFFSET MSG

MOV АН,41Н /атрибут

CALL WRITE

/Здесь можно   записать   какую-либо  команду,    вызывающую ошибку /здесь  цикл,    выйти из  которого можно только по  ошибке либо /по  нажатии клавиши ESC _WAI:   JMP SHORT _WAI

процедур /установка   защищенного режима

SET_PROT PROC NEAR MOV _ss,ss

MOV _ES,ES

INT_22

INT_23

INT_24 INT_25 INT_26

INT 27

INT_28 INT_29

INT_2A

INT_2B

INT 2C INT_2D INT_2E INT_2F

CALL ENABLE

CALL PROG_INT ;загрузить регистр прерываний

LIDT QWORD  PTR GDT_IDT ;загрузить регистр  глобальной дескрипторной таблицы

LGDT QWORD PTR GDT_GDT /устанавливаем защищенный режим MOV ' АХ, 1

АХ

— JMP   FAR FLUSH, для  сбрасывания  очереди команд

DB

DW DW

FLUSH: ;загрузка

MOV MOV

ОЕАН

OFFSET FLUSH (GDT_CS-GDTO)

селекторов АХ, (GDT_DS-GDTO) DS,AX MOV AX,SEL_BUF MOV ES,AX

MOV    AX,(GDT_SS-GDTO) MOV SS,AX

прерывания на

XOR AL,AL OUT 21H,AL

OUT OA1H,AL XOR DL,DL

прерывания на

STI RETN

SET_PROT ENDP

линии

ENABLE PROC NEAR

MOV    AL,0D1H OUT 64H,AL

MOV AL,ODFH OUT 60H,AL

RETN

ENABLE ENDP /запрещение линии А2 0 DISABLE PROC NEAR

MOV  AL,0D1H OUT 64H,AL MOV AL,ODDH OUT 60H,AL

RETN

уровне контроллера

уровне микропроцессора

/команда управления линией А2 0 /порт состояния клавиатуры /открыть А2 0 /клавиатурный порт

/закрыть А20

DISABLE ENDP

;звуковой сигнал

/процедура взята из главы 6  (Рис. 6.5) SOUND PROC NEAR

PUSH АХ

PUSH СХ

MOV AL,10110110В /установка режима записи

OUT 43H,AL IN   AL,61H

OR   AL,3      . /разрешить связь с таймером

OUT 61H,AL

MOV AX,1200 / установить частоту звука

OUT 42H,AL

MOV AL,AH

OUT 42H,AL

MOV CX,0FFFFH ;задержка LOO: LOOP LOO

MOV CX,0FFFFH /задержка LOOl:   LOOP L001

./отключить канал от динамика,   т.е.   прекратить звук IN   AL,61Н AND AL,11111100В

OUT 61H,AL POP CX POP AX

RET SOUND ENDP

/ перепрограммирование  контроллера прерываний PROG_INT PROC NEAR контроллер /прерывания 0-7  получают номера 20Н-27Н

MOV AH,20H ■

MOV AL,11H

OUT 20H,AL

JMP SHORT $+2

MOV AL,AH

OUT 21H,AL

JMP SHORT $+2

MOV AL,4 OUT 21H,AL

MOV AL, 1 OUT 21H,AL JMP   SHORT $+2 MOV AL,OFFH OUT 21H,AL

JMP SHORT $+2

/второй контроллер

/прерывания 8-15 получают номера 28H-2FH MOV АН,28Н MOV AL,11H

OUT OAOH,AL JMP SHORT $+2

MOV AL,АН OUT 0A1H,AL

JMP SHORT $+2

MOV AL, 4 OUT 0A1H,AL

JMP SHORT $+2

MOV AL, 1 OUT 0A1H,AL

JMP SHORT $+2 MOV AL,OFFH OUT OA1H,AL JMP SHORT $+2

RETN PROGINT ENDP

; определение параметров видеосистемы WHAT_CRT PROC NEAR

MOV AX,40H •MOV ES,AX

MOV BX,ES:[4AH]

MOV  COLUMNS, BL

MOV BL,ES:[84H]

INC BL

MOV ROWS,BL

MOV BX,ES:[63H]

CMP BX,3D4H

JNE NO_COLOR /цветной адаптер

MOV-SEL_BUF, (GDT_CRT-GDTO)

MOV  SEGJBUF,0B800H

MOV

. JMP   SHORT EXIT NO COLOR:

; адаптер MDA

MOV SEL_BUF,(GDT_MDA-GDTO) MOV SEG_BUF,0B000H MOV ES,SEG_BUF

EXIT:

RETN WHAT_CRT ENDP

;вывод на  экран строки

; в ES либо селектор экрана, либо сегмент ;АХ,ВХ X,Y

- адрес строки ;АН - атрибут WRITE -PROC NEAR /расчет смещения  в видеопамяти

PUSH AX

MOV DL, COLUMNS MUL DL ADD АХ,ВХ ' SHL АХ,1 MOV DI,AX POP AX

L01:

LODSB

CMP AL, 0 JZ EN STOSW

SHORT L01

EN:

RETN WRITE ENDP

клавиатурного прерывания END_INT PROC NEAR

IN AL,61H

MOV AH,AL

OR AL,80H

OUT 61H,AL

XCHG AH,AL

OUT 61H,AL

MOV AL,20H

OUT 20H,AL

RETN END_INT ENDP

KEY   PROC NEAR

PUSH AX CALL SOUND

IN

CMP   AL, 1 JNZ NO_ESC

CALL END_INT

MOV    _DL,4 8 CALL SET__REAL NO_ESC:

;-конец ;выход из  защищенного режима

прерывания

CALL END_INT POP AX IRET

KEY ENDP

;обработка прерывания таймера

;вызывает звуковой сигнал,   примерно раз   в секунду

TIMER PROC NEAR

CLI

PUSH AX

MOV АХ,TIME

CMP АХ,18

. JNZ DAL

MOV TIME,0

DAL:

DAL1:

CALL SOUND

JMP    SHORT DAL1

INC TIME

MOV AL,2 0H OUT 20H,AL

POP AX IRET TIMER ENDP

/обработчик прерываний INT1 PROC NEAR PUSH AX

MOV     AL,2 0H OUT 20H,AL POP AX MOV    _DL,50

■ IRET

INT1 ENDP

;обработчик прерываний INT2  PROC NEAR PUSH AX

MOV AL,20H

от первого контроллера

от  второго контроллера

OUT    2 0H,AL OUT    0AH,AL POP AX MOV _DL,51 IRET INT2 ENDP

;обработка исключений EX00   PROC NEAR

MOV    _DL,52   ; 1-е исключение

CALL SOUND CALL SOUND

JMP SET_REAL EXOO ENDP EX01   PROC NEAR

MOV   _DL, 53   ; 1-е исключение

CALL SOUND

CALL SOUND

JMP SET_REAL EX01 ENDP EX02 PROC NEAR

MOV _DL,54  ; 2-е исключение

CALL SOUND

CALL SOUND

JMP SET_REAL

EX02 ENDP

EX03 PROC NEAR

MOV 3-е исключение

CALL SOUND CALL

JMP SET_REAL EX03 ENDP

EX 04   PROC NEAR

MOV    _DL,56   ;4-e исключение

CALL SOUND

CALL SOUND

JMP SET_REAL ENDP

PROC NEAR

MOV _DL,57   ;5-e исключение

CALL SOUND

CALL SOUND

JMP SET_REAL

ENDP

EX06  PROC NEAR

MOV   _DL, 58   ; 6-е исключение CALL SOUND

CALL SOUND

SET_REAL

EXQ6 ENDP

EXQ7   PROC NEAR

MOV исключение

CALL SOUND

CALL SOUND

JMP SET_REAL EXQ7 ENDP EXQ8 PROC NEAR

MOV   _DL,60   ; 8-е исключение

CALL SOUND

CALL

JMP SET_REAL ENDP

PROC NEAR

MOV исключение

CALL SOUND CALL SOUND JMP SET_REAL ENDP EXOA PROC NEAR

MOV исключение

CALL SOUND

CALL SOUND

JMP SET_REAL EXOA ENDP

EXOB   PROC NEAR

MOV исключение

CALL SOUND

CALL SOUND

JMP SET_REAL EXOB ENDP EXOC PROC NEAR

MOV исключение

CALL SOUND

CALL SOUND

JMP SET_REAL EXOC ENDP EXOD PROC NEAR

MOV исключение

CALL SOUND

CALL SOUND

JMP SET_REAL

EXOD ENDP EXOE PROC NEAR

MOV   _DL,66   ;EH-e исключение CALL SOUND

CALL SOUND

JMP SET_REAL

EXOE ENDP EXOF PROC NEAR

MOV исключение

CALL SOUND CALL SOUND

JMP SET_REAL

EXOF ENDP

PROC NEAR

MOV исключение

CALL SOUND CALL SOUND

JMP SET_REAL

EXlQ ENDP

EX11   PROC NEAR

MOV исключение

CALL SOUND CALL SOUND

JMP SET_REAL

EXll ENDP

EX 12   PROC NEAR

MOV исключение

CALL SOUND CALL SOUND

JMP SET_REAL

EXl2 ENDP

EX 13   PROC NEAR

MOV исключение

CALL SOUND CALL SOUND

JMP SET_REAL

EXl3 ENDP

EX 14   PROC NEAR

MOV исключение

CALL SOUND

CALL SOUND

JMP   SET REAL

ЕХ14 ENDP

ЕХ15     PROC NEAR

MOV    _DL,73  ;15Н-е исключение

CALL SOUND

CALL SOUND

JMP SET_REAL

ЕХ15 ENDP

EX16  PROC NEAR

MOV    _DL,74   ;16H-e исключение CALL SOUND CALL SOUND JMP SET_REAL

ENDP

ЕХ17   PROC NEAR

MOV    _DL,75  ;17H-e исключение

CALL SOUND CALL SOUND JMP SET_REAL

ЕХ17 ENDP

ЕХ18     PROC NEAR

MOV    _DL,76   ;18H-e исключение

CALL SOUND

CALL SOUND

JMP SET_REAL ENDP

ЕХ19     PROC NEAR

MOV   _DL,77   ;19H-e исключение

CALL SOUND CALL SOUND JMP SET_REAL

ЕХ19 ENDP

ЕХ1А     PROC NEAR

MOV   _DL,78   ; lAH-e исключение

CALL SOUND CALL SOUND JMP SET_REAL

EX1A ENDP

EX1B     PROC NEAR

MOV   _DL,79   ; lBH-e исключение

CALL SOUND CALL SOUND JMP SET_REAL

EX1B ENDP

EX1C   PROC NEAR

MOV _DL, 80   ; 1СН-е исключение

CALL SOUND

CALL SOUND

JMP SET REAL EX1C ENDP

EX1D PROC NEAR

MOV исключение

CALL SOUND

CALL SOUND

JMP SET_REAL EX1D ENDP EX1E PROC NEAR

MOV исключение

CALL SOUND CALL SOUND JMP SET_REAL EX1E ENDP

PROC NEAR

MOV исключение

CALL SOUND

CALL SOUND

JMP SET_REAL ENDP PAUSE PROC

PUSH CX

MOV CX,550

PL:

PUSH CX

MOV CX,OFFFFH

PL1:

LOOP PL1

POP CX

LOOP PL

POP CX RETN

PAUSE ENDP

;сообщение об ошибке и возврат в реальный режим ;возврат в реальный режим

SET_REAL PROC NEAR

CLI

CALL DISABLE ;запомнить содержимое  регистра стека MOV SP,SP

/сброс процессора MOV AL,OFEH

OUT 64H,AL

;ожидание возврата по метке SHUT_DOWN_RETURN _WAIT:

JMP _WAIT ; —теперь мы в реальном режиме— /метка возврата SHUT_DOWN_RETURN:

/•восстанавливаем значения  всех сегментных регистров MOV АХ,DATA MOV DS,AX

MOV

MOV SP,_SP

MOV ES,_ES ;немаскируемые прерывания MOV   AX,ODH OUT 70H,AL

/маскируемые прерывания на уровне  контроллера прерываний XOR    AL,AL OUT 21H,AL OUT    0А1Н, AL

/маскируемые прерывания на уровне микропроцессора STI

MOV

MOV   АН, 2 INT 21H MOV    АН,4СН

INT 21H RETN SET_REAL ENDP

/процедура   инициализации   защищенного режима INI_PROT PROC

/заполнение таблицы прерываний /заполнение gdt

MOV

MOV DS,AX

MOV DL, AH

SHR DL,4

SHL AX,4

MOV SI,AX

MOV DI,DX

АвЗЕМВЬЕКУчебный курс

-■-дескриптор для GDT

ADD АХ,OFFSET GDT0 ADC DL,0

MOV BX,OFFSET GDT_GDT

MOV WORD PTR   [BX] ,GDT_SIZE-l

MOV [BX+2],AX

MOV [BX+4],DL

MOV BYTE   PTR   [BX+5],DATA_AC

-дескриптор сегмента данных

MOV BX,OFFSET GDT_DS MOV AX,Sr MOV DX,DI

MOV WORD PTR   [BX] ,DSEG_SIZE-l MOV [BX+2],AX MOV [BX+4],DL

MOV BYTE   PTR    [BX+5] , DATA_AC

-дескриптор сегмента кода

MOV BX,OFFSET GDT_CS

MOV

MOV DL,AH SHR DL, 4 SHL AX, 4

MOV WORD  PTR   [BX] , CSEG_SIZE-1

MOV [BX+2],AX

MOV [BX+4],DL

MOV BYTE   PTR    [BX+5] , CODE AC

MOV BX,OFFSET GDT_SS

MOV

MOV DL,AH

SHR DL, 4

SHL AX,4

MOV WORD  PTR   [BX], 400-1 MOV [BX+2],AX

MOV [BX+4],DL

MOV BYTE PTR AC

MOV BX,OFFSET GDT_CRT MOV WORD PTR   [BX], 3999 MOV WORD  PTR   [BX+2], 8000H . MOV BYTE   PTR [BX+4],0BH MOV BYTE   PTR   [BX+5] , DATA AC

MOV WORD  PTR [ВХ],3999 MOV BYTE   PTR [BX+4],0BH MOV BYTE   PTR    [BX+5] , DATA_AC

-структура для таблицы прерываний

MOV BX,OFFSET GDT_IDT MOV AX,DS MOV DL,AH SHR DL, 4 SHL AX,4

ADD AX,OFFSET EXC_00 ADC  DL, 0

MOV WORD   PTR [BX],IDT_SIZE-1 MOV WORD  PTR [BX+2],AX MOV BYTE   PTR [BX+4],DL MOV BYTE   PTR    [BX+5] , IDT_AC -исключения

MOV AX,OFFSET EXOO MOV BX,OFFSET EXC_0 0 MOV [BX],AX

MOV WORD PTR   [BX+2] , (GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE   PTR    [BX+5] ,TRAP_AC

MOV AX,OFFSET EX01 MOV BX,OFFSET EXC_01 MOV [BX],AX

MOV WORD PTR   [BX+2] , (GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE  PTR   [BX+5] , TRAP_AC

MOV EX02

MOV BX,OFFSET EXC_02 MOV [BX],AX

MOV WORD PTR   [BX+2]  , (GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE   PTR    [BX+5],TRAP_AC

MOV AX, OFFSET EX03 MOV BX,OFFSET EXC_03 MOV [BX],AX

MOV WORD  PTR   [BX+2] , (GDT_CS-GDTO)

MOV BYTE PTR [BX+4],0

MOV BYTE PTR   [BX+5],TRAP AC

MOV AX,OFFSET EX04 MOV BX, OFFSET EXC04 MOV [BX],AX

mov word  ptr   [bx+2], (gdt_cs-gdto)

mov byte   ptr [BX+4],0

mov byte  ptr   [BX+5], TRAP AC

mov

mov BX,OFFSET exc_05 .

mov [BX],AX

mov word  ptr [BX+2] , (GDT_CS-GDTO)

mov byte  ptr [BX+4],0

mov byte  ptr [BX+5] , TRAP_AC

mov

mov BX,OFFSET exc_06

mov

mov word  ptr    [BX+2] , (GDT_CS-GDTO)

mov byte  ptr [BX+4],0

mov byte  ptr    [BX+5], TRAP AC

mov AX/OFFSET ex07 mov BX,OFFSET EXC_07 mov [BX],AX

mov word ptr [BX+2] , (GDT_CS-GDTO) mov byte   ptr [BX+4],0

mov byte  ptr   [BX+5] ,trap_ac

mov

mov BX,OFFSET EXC_08 mov [BX],AX

mov  word   ptr [bx+2] ,   (gdt_cs-gdto)

mov byte   ptr [BX+4],0

mov byte   ptr [BX+5], TRAP AC

mov AX,OFFSET ex0 9 mov BX,OFFSET exc_09 mov [BX],AX

mov word PTR [bx+2] , (gdt_cs-gdto) mov byte   ptr [BX+4],0

mov byte ptr

mov exoa

mov BX,OFFSET exc oa

mov

mov word   ptr  [bx+2] , (gdt_cs-gdto)

mov byte ptr

mov byte  ptr   [BX+5] ,TRAP_ac

mov exob

mov exc_ob mov

MOV WORD PTR   [BX+2] ,   (GDT_CS-GDTO)

mov byte ptr

mov byte  ptr    [BX+5] ,trap_ac

mov exoc

mov exc_oc mov

mov word  ptr    [bx+2], (gdt_cs-gdto)

MOV BYTE   PTR [BX+4],0

mov byte ptr

mov exod

mov exc_od mov

mov word ptr

mov byte ptr

mov byte ptr

mov exoe

mov exc_oe mov

mov word  ptr    [bx+2] , (gdt_cs-gdto)

mov byte ptr

mov byte ptr

mov AX,OFFSET exof

mov BX,OFFSET exc_of

mov

MOV WORD  PTR    [BX+2] , (GDT_CS-GDTO)

mov byte ptr

mov byte ptr

mov ex10

MOV BX,OFFSET EXC_10

mov

MOV WORD PTR   [BX+2], (GDT CS-GDTO)

MOV BYTE PTR  [BX+5],TRAP_AC

MOV EXll

MOV BX, OFFSET EXCJ1 MOV [BX],AX

MOV WORD PTR   [BX+2],  (GDT_C S - GDTO)

MOV BYTE PTR MOV BYTE PTR

MOV EXl2

MOV BX,OFFSET EXC_12

MOV

MOV WORD PTR

MOV  BYTE   PTR [BX+4],O

MOV BYTE PTR

MOV AX,OFFSET EX13 MOV  BX,OFFSET EXC_13

MOV

MOV WORD PTR [BX+2] , (GDT_CS-GDTO) MOV BYTE   PTR [BX+4],0

MOV BYTE PTR

MOV AX,OFFSET EX14

MOV BX,OFFSET EXC_14

MOV

MOV WORD   PTR [BX+2] , <GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE   PTR [BX+5] , TRAP_AC

MOV

MOV BX,OFFSET EXC_15 MOV    [BX],AX

MOV WORD PTR

MOV BYTE

MOV BYTE PTR

MOV MOV

MOV " [BX] , AX

MOV WORD PTR   [BX+2]  , (GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV AX,OFFSET EX17 MOV BX,OFFSET EXC_17 MOV [BX],AX

MOV WORD PTR   [BX+2] ,   (GDT_CS-GDTO)

MOV BYTE ' PTR    [BX+4],0

MOV BYTE   PTR    [BX+5],TRAP_AC

MOV AX,OFFSET EX18

MOV BX,OFFSET EXC_18

MOV [BX],AX

MOV WORD  PTR    [BX+2],(GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE   PTR   [BX+5], TRAP AC

MOV AX,OFFSET EX19

MOV BX,OFFSET EXC_19 MOV [BX],AX

MOV WORD   PTR [BX+2],(GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE   PTR [BX+5] , TRAP_AC

MOV AX,OFFSET EX1A

MOV BX,OFFSET EXC_1A MOV [BX],AX

MOV WORD' PTR    [BX+2]  ,   (GDT_C S - GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE   PTR [BX+5], TRAP AC

MOV AX,OFFSET EX1B

MOV BX,OFFSET EXC_1B

MOV [BX],AX

MOV WORD   PTR [BX+2],(GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE   PTR [BX+5] , TRAP__AC

MOV AX,OFFSET EX1C

MOV BX,OFFSET EXC_1C

MOV [BX],AX

MOV WORD PTR   [BX+2] ,   (GDT_C S - GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE   PTR [BX+5] , TRAP_AC

MOV EX1D

MOV BX,OFFSET EXC_1D

/

20 - 4072

MOV WORD PTR [BX+2],  (GDT_CS-GDTO)

MOV BYTE PTR [BX+4 3,0

MOV BYTE PTR [BX+5] , TRAP_AC

MOV AX,OFFSET EX1E MOV BX,OFFSET EXC_1E MOV [BX],AX

MOV WORD PTR   [BX+2] ,   (GDT_C S - GDTO)

MOV  BYTE   PTR [BX+4],0

MOy- BYTE PTR   [BX+5]  , TRAP_AC

MOV AX,OFFSET EXIF

MOV  BX,OFFSET EXC_1F MOV [BX],AX

MOV WORD PTR   [BX+2] ,   (GDT_C S - GDTO)

MOV  BYTE   PTR [BX+4],0

MOV BYTE   PTR    [BX+5] , TRAP_AC

-прерывания

MOV AX,OFFSET TIMER MOV BX,OFFSET   INT_2 0 MOV [BX],AX

MOV WORD   PTR    [BX+2], (GDT_CS-GDTO)

MOV  BYTE   PTR [BX+4],0

MOV  BYTE   PTR    [BX+5] , INT_AC

MOV AX,OFFSET KEY

MOV BX,OFFSET INT_21 MOV [BX],AX

MOV WORD   PTR [BX+2], (GDT_CS-GDTO)

MOV  BYTE    PTR [BX+4],0

MOV BYTE   PTR [BX+5], INT AC

MOV AX,OFFSET INT1

MOV BX, OFFSET INT_22 MOV [BX],AX

MOV WORD   PTR [BX+2] , (GDT_CS-GDTO)

MOV  BYTE   PTR [BX+4],0

MOV BYTE   PTR [BX+5], INT AC

MOV AX,OFFSET INT1

MOV BX,OFFSET INT_23

MOV [BX],AX

MOV WORD   PTR    [BX+2],   (GDT CS-GDTO)

MOV BYTE PTR

MOV BYTE PTR  [BX+5],INT AC

MOV AX,OFFSET INT1 MOV BX, OFFSET INT 24 MOV [BX],AX

MOV WORD PTR MOV BYTE PTR MOV BYTE PTR

MOV

MOV BX,OFFSET MOV [BX],AX

MOV WORD PTR MOV BYTE PTR MOV BYTE PTR

MOV

MOV BX,OFFSET MOV [BX],AX

MOV WORD PTR MOV BYTE PTR MOV BYTE PTR

MOV AX,OFFSET INT1

MOV BX,OFFSET INT_27 MOV [BX],AX

MOV WORD   PTR    [BX+2] , (GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE PTR

MOV INT2

MOV BX,OFFSET INT_28

MOV

MOV WORD   PTR [BX+2],(GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE   PTR [BX+5] , INT AC

MOV INT2

MOV BX,OFFSET INT_29

MOV [BX],AX

MOV WORD   PTR    [BX+2], (GDT_CS-GDTO)

MOV BYTE PTR

MOV BYTE   PTR    [BX+5], INT AC

[BX+2] , (GDT_CS-GDTO) [BX+4],0 [BX+5],INT_AC

INTl

INT_25

[BX+2] ,   (GDT_CS-GDTO) [BX+4],0 [BX+5],INT_AQ

INTl

INT_26

[BX+2] , (GDT_CS-GDTO) [BX+4],0 [BX+5],INT AC

20-

MOV AX,OFFSET INT2 MOV BX,OFFSET INT_2A MOV [BX],AX

MOV WORD PTR MOV BYTE PTR MOV BYTE PTR

MOV INT2

MOV BX,OFFSET INT_2B

MOV

MOV WORD PTR [BX+2], (GDT_CS-GDTO) MOV BYTE   PTR [BX+4],0

MOV BYTE PTR

MOV INT2

MOV BX,OFFSET INT_2C

MOV

MOV WORD   PTR    [BX+2], (GDT_CS-GDTO)

MOV BYTE PTR MOV BYTE PTR

MOV INT2

MOV BX,OFFSET INT_2D

MOV

MOV WORD   PTR    [BX+2], (GDT_CS-GDTO)

MOV BYTE PTR

MOV BYTE

MOV INT2

MOV BX,OFFSET INT_2E

MOV

MOV WORD PTR   [BX+2], (GDT_CS-GDTO)

MOV BYTE PTR

MOV  BYTE   PTR [BX+5],INT_AC

MOV INT2

MOV BX, OFFSET INT_2F

MOV

MOV WORD PTR [BX+2] , (GDT_CS-GDTO) MOV BYTE   PTR [BX+4],0

;-адрес возврата из защищенного режима

PUSH DS MOV АХ,40Н MOV DS,AX

MOV    WORD PTR DS:[67H],OFFSET SHUT_DOWN_RETURN MOV DS:[69H],CS

POP DS

/записываем в ячейку OFH CMOS код 5 /чтобы обеспечить возврат после сброса процессора CLI

MOV AL,8FH

OUT 70H,AL

JMP $+2

MOVAL,5

OUT 71H,AL

RETN INI PROT ENDP CSEG_SIZE=$-BEGIN CODE ENDS

END BEGIN

Рис. 20.3. Пример программы, работающей в защищенном режиме с обработкой

прерываний.

Разберем программу на Рис. 20.3. Если говорить о структуре данных программы, то отличие отдвух предыдущих программ данной главы заключается в том, что появилась еще таблица прерываний. Заполнение этой таблицы, как и остальных дескрипторов, производится процедурой INI_PROT. Каждому элементу таблицы прерываний соответ­ствует своя процедура обработки. При возникновении исключения производится выход из программы с передачей кода ошибки в ячейку _DL. Особо обрабатываются прерыва­ния от таймера и клавиатуры. Процедура обработки таймера производит звуковой сиг­нал приблизительно раз в секунду. Звуковой сигнал включаетсяи при нажатии клавиши. При нажатии клавиши ESC программа прерывается и происходит выход в реальный режим. Программа максимально упрощена, поэтому при выходе выводится не код ошиб­ки, а символ, соответствующий данному коду. Чтобы проверить работу исключений, нужно nepeflMeraoH_WAInocTaBHTb какую-либо команду, вызываюпгую ошибку. Такой командой может быть, например, команда записи в сегмент кода: MOV WORD PTR CS:_WAIT,90. Выполнить процедуру исключения можно и непосредственно командой INT. Отсюда ясно, как создавать новые прерывания. Достаточно добавить к таблице прерывания еще один дескриптор, указывающий/на соответствующую процедуру. Но­мер вектора определится порядковым номером дескриптора в таблице. Вызов такого прерывания, естественно, будет осуществляться командой INT.

И последний пример данной главы. Часть, обрабатывающая прерывания, практи­чески совпадает с аналогичной частью в предыдущей программе. Что же здесь ново­го? Во-первых, вход и выход из защищенного режима производится командами 386-гопроцессора. Во-вторых, здесь демонстрируется, как в принципе можно сочетать за­щищенный режим и работу с файлами.

Обратимся вначале к командам 386-го процессора. Переход в защищенный режим производится установкой бита G в регистре CRO (см. главу 2G). Вот и все, все осталь­ное так же, как и для 286-го процессора. Выход из защищенного режима несколько сложнее. Мы действовали согласно алгоритму, приведенному во многих книжках по 386-му и 486-му процессорам (см. [19,22,25]). Вот этот алгоритм:

Если разрешено страничное преобразование, выполняются следующие опе­рации:

- передать управление линейным адресам, имеющим тождественное отобра­жение, т.е. линейные адреса равны физическим адресам;

- сбросить бит PG в регистре CRO;

- передать ноль в регистр CR3 для очистки буфера страниц.

В нашем случае страничная адресация не вводилась, поэтому первый пункт можно не выполнять.

2. Передать управление сегменту, который имеет предел При в регистр CS загружается предел сегмента, который он должен иметь в реальном режиме. В нашем случае изначально в регистр C S заложен селектор с указанными пара­метрами.

3. Загрузить в сегментные регистры SS, DS, ES, FS и GS селектор для для деск­риптора, содержащего следующие значения:

- предел

- байтная гранулярность (G=G),

- расширение вверх,

- сегмент записываемый,

- присутствующий в памяти,

- значение.

В нашем случае регистры SS, DS, ES изначально загружаются такими селекто­рами. Регистры же FS, GS мы нигде не используем.

4. Запретить прерывания.

5. Сбросить нулевой битв CRO.

6. Перейти к программе реального режима путем дальнего перехода, для очистки очереди.

У. Загрузить регистр прерываний. Перед выходом в защищенный режим мы со­хранили этот регистр, а потом восстановили. Кроме того, нужно снова пере­программировать контроллер прерываний для реального режима.

8. Разрешить прерывания.

9. Загрузить сегментные регистры.

Именно по такой схеме мы действовали в данном случае. Читатель уже, наверное, задал себе важный вопрос, как работать с файлами в защищенном режиме. Автор ви­дит три пути решения данной проблемы:

1. Каким-то образом, находясь в защищенном режиме, использовать стандартные процедуры DOS. Наверное, в силу своей близорукости я не вижу, как это сде­лать достаточно просто.

2. Написать собственную библиотеку работы с файлами или использовать стан­дартные библиотеки.

3. Перед обращением к какой-либо DOS-овской процедуре выйти в реальный ре­жим, а потом снова вернуться в защищенный.

Последний подход и реализован вданном примере. Может возникнуть вопрос, как в защищенном режиме загружать большие объемы информации. Это можно сделать через промежуточный буфер, который будет находиться в сегменте данных, доступ к которому, естественно, будет как в защищенном, так и в реальном режиме. Похоже, что именно такой подход был реализован и в старой Windows 3.1.

;работаем в защищенном режиме 386-го процессора .386Р

/байты доступа

;10000000В - сегмент есть в памяти ;00011000В -  сегмент кода ;00010000В -  сегмент данных ;00000100В -   сегмент расширяется вниз ; 00000100В -   согласованный сегмент ; 00000010В -  разрешена записв ; 00000110В -  вентиль прерывания ; 00000111В -   вентиль исключения ; сегмент данных DATA_AC      EQU 10010010В кода

CODE_AC     EQU 10011000B стека

STACK_AC   EQU 10010110B ;сегмент таблицы IDT IDT_AC       EQU 10010010B

доступа   вентиля прерывания INT_AC        EQU 10000110B

доступа   вентиля исключения TRAP_AC     EQU 10000111B стека

ST1   SEGMENT   STACK 'STACK'

DB   100 DUP(?) ST1 ENDS ;сегмент данных DATA SEGMENT BEG_DATA= $ _SS    DW ? _ES    DW ? IDTT DQ ?

MSG    DB   'Перешли в   защищенный режим.', MSG1   DB 'Открыли файл и перешли в  защищенный режим. ',0

MSG2   db 'Записали в  файл и перешли в  защищенный режим. ',0

MSG3  db ' Закрыли файл и перешли в защищенный режим. ',0

path  db 'PROT.TXT',О

buf    db 'Файл проверки' _DL DB O

/здесь будет храниться дескриптор файла

_АХ DW ?

/данные для  вывода на экран

columns db  ? ;количество столбцов на экране

ROWS      DB ? /количество строк на экране

sel_buf dw   ? ;селектор видеобуфера

seg_buf dw ? /сегментный  адрес видеобуфера

/глобальная  дескрипторная таблица

/нулевой дескриптор

GDTO dq о

для GDT GDT_GDT   DQ О

/дескриптор для сегмента кода GDT_CS    DQ О

/дескриптор для  сегмента данных

GDT_DS    DQ О

/дескриптор для сегмента стека GDT_SS    DQ О

для   видеопамяти цветного дисплея

GDT_CRT   DQ О

/дескриптор для   видеопамяти монохромного дисплея

GDT_MDA   DQ О

/дескриптор таблицы прерываний gdt_idt    dq О

GDT_SIZE = $-GDTO     /размер глобальной дескрипторной таблицы

; вентили исключений

IDT BEG=$

ЕХС_00

DQ

O

ЕХС_01

dq

O

ЕХС_02

DQ

O

ЕХС_0 3

DQ

O

ЕХС_04

dq

O

ЕХС_05

DQ

O

ЕХС_0 б

DQ

O

ЕХС_07

DQ

O

ЕХС__08

DQ

O

ЕХС_0 9

dq

O

ЕХС_ОА

DQ

O

ЕХС_ОВ

DQ

O

Глава 26. в защищенном режиме

ЕХС_ОС

DQ

О

EXC_OD

DQ

О

ЕХС_ОЕ

DQ

О

EXC_OF

DQ

О

EXC_JLO

DQ

О

ЕХС_11

DQ

О

ЕХС_12

DQ

О

ЕХС_13

DQ

О

ЕХС__14

DQ

О

ЕХС__15

DQ

О

ЕХС_16

DQ

О

ЕХС__17

DQ

О

ЕХС_18

DQ

О

ЕХС_19

DQ

О

ЕХС_1А

DQ

0

ЕХС_1В

DQ

О

ЕХС_1С

DQ

о ■

EXC__1D

DQ

О

ЕХС_1Е

DQ

О

EXC_1F

DQ

О

прерываний

;таймер ;клавиатура

ЮТ_2о ШТ_21 INT_22

INT_23

INT__24 INT__25 INT_26 INT__27 INT_28 INT_29

INT_2A INT_2B INT_2C

INT__2D

INT_2E INT_2F

IDT SIZE=$-IDT BEG

DQ

о

DQ

о

DQ

О

DQ

о

DQ

о

DQ

о

DQ

о

DQ

о

DQ

о

DQ

о

DQ

о

DQ

О

DQ

о

DQ

о

DQ

о

DQ

о

таблицы прерываний

DSEG_SIZE=$-BEG_DATA  ;размер сегмента данных

DATA ENDS

кода

CODE   SEGMENT   PUBLIC   PARA USE16

ASSUME CS:CODE,   DS:DATA, SS:ST1

MOV AX,DATA MOV DS,AX

MOV _DL,0 ; сохраняем сегменты MOV_ES,ES MOV_SS,SS SIDT OWORD PTR IDTT

CALL WHAT_CRT ;войти в  защищенный режим

CALL SETJPROT ;очистить экран

MOV АН,07Н

CALL CLS ;координаты

MOV BX, 0    ; координата X

MOV АХ, 2     ;координата Y ;адрес выводимой строки

MOV SI,OFFSET MSG

MOV АН,4ОН /атрибут

CALL WRITE /здесь работаем с файлами /открыть файл

CALL SET_REAL

MOV АН,ЗСН LEA    DX,PATH MOV    СХ, О

INT 21H

MOV _АХ,АХ

CALL SET_PROT /координаты

MOV ВХ,0      /координата X

MOV АХ,3      /координата Y /адрес выводимой строки

MOV SI,OFFSET MSG1

MOV АН,41Н /атрибут

CALL WRITE

/следующая команда,   если   снять с нее комментарий /приведет  к  аварийному выходу из программы MOV BYTE  PTR CS:_END,AL туда

CALL SET_REAL

MOV    BX, AX

LEA DX,BUF

MOV СХ,13

MOV    АН,4ОН

int 21н

CALL SET_PROT ;координаты

MOV ВХ,0      /координата X

MOV АХ, 4      /координата Y /адрес выводимой строки

MOV SI,OFFSET MSG2

MOV АН,41Н    /атрибут.

CALL WRITE /закрыть файл

CALL SET_REAL

MOV ВХ,_АХ MOV    АН,ЗЕН

INT 21H

CALL SET_PROT

;координаты

MOV X MOV АХ, 5      /координата Y

/адрес выводимой строки MOV  SI,OFFSET MSG3 MOV АН,41Н /атрибут

CALL WRITE /выход

CALL SET_REAL

MOV _DL, 48

_END:

MOV

MOV   АН, 2 -

INT 21H

MOV    АН,4CH

INT 21H /раздел процедур /возврат в реальный режим

SET_REAL PROC NEAR MOV

MOV ES,AX MOV AX,CR0 AND    AX,OFFFEH /переход в реальный режим MOV    CRO,AX

/—теперь мы в реальном режиме—

-JMP FAR FLUSH,  для сбрасывания очереди команд

DB ОЕАН

DW      OFFSET FLUSH DW      SEG FLUSH

FLUSH:

/перепрограммировать  контроллер прерываний

CALL PROG_INT1 /восстановить сегментные регистры

MOV АХ,DATA

MOV DS,AX

MOV SS,_SS

MOV ES,_ES /восстановить регистр прерываний

LIDT QWORD PTR IDTT /запретить  линию А20

CALL DISABLE

/разрешить   немаскируемое прерывание MOV   АХ,ODH OUT 70H,AL

STI

CMP    _DL,0

JNZ _END RETN

SET_REAL ENDP

/установка  защищенного режима

SET_PROT PROC NEAR

/инициализировать дескрипторные таблицы

CALL INI_PROT

CLI

/разрешить линию CALL ENABLE

/перепрограммировать  контроллер прерываний

CALL PROG_INT

/загрузить регистр прерываний

LIDT  QWORD  PTR GDT_IDT /загрузить регистр  глобальной дескрипторной таблицы

LGDT QWORD PTR GDT_GDT

/устанавливаем защищенный режим MOV AX,CR0 OR    АХ, 1 MOV CR0,AX

/-JMP FAR FLUSH1,   для  сбрасывания  очереди команд

DB ОЕАН

DW      OFFSET FLUSH1 DW <GDT_CS-GDTO) FLUSH1:

селекторов MOV    AX, (GDT_DS-GDTO) MOV    DS, AX MOV AX,SEL_BUF MOV ES,AX ■ MOV    AX, (GDT_SS-GDTO) MOV SS,AX

прерывания на уровне контроллера

XOR AL, AL OUT 21H,AL

OUT OA1H ,AX

;размаскировать прерывания на уровне микропроцессора STI RETN

SET_PROT ENDP

линии

ENABLE PROC NEAR

MOV   AL,0D1H       ;команда управления линией А20 OUT состояния клавиатуры

MOV    AL,0DFH       /открыть A2 0

OUT порт

RETN ENABLE ENDP ;запрещение линии А20 DISABLE PROC NEAR

MOV AL,OD1H

OUT 64H,AL

MOV AL,ODDH ;закрыть A2 0

' OUT 60H,AL

RETN DISABLE ENDP

;перепрограммирование контроллера прерываний PROG_INT PROC NEAR контроллер /прерывания 0-7   получают номера •20Н-27Н

MOV

MOV AL,11H OUT 20H,AL

JMP   SHORT $+2

MOV

OUT 21H,AL JMP   SHORT $+2 MOV AL, 4 OUT 21H,AL

JMP SHORT $+2

MOV AL,1

OUT 21H,AL

JMP SHORT $+2

MOV AL,OFFH

OUT 21H,AL

JMP SHORT $+2

;второй контроллер

;прерывания  8-15   получают номера

•28H-2FH

MOV

AH,28H

MOV

AL,11H

OUT

OAOH,AL

JMP

SHORT $+2

MOV

AL, AH

OUT

OA1H,AL

JMP

SHORT $+2

MOV

AL,2

OUT

0A1H,AL

JMP

SHORT $+2

MOV

AL, 1

OUT

OA1H,AL

JMP

SHORT $+2

MOV

AL,OFFH

OUT

0A1H,AL

JMP

SHORT $+2

RETN

PROG_INT ENDP ■ /перепрограммирование  контроллера прерываний PROG_INT1   PROC NEAR контроллер

0-7  получают номера MOV AL,11H OUT   2 0H,AL

JMP SHORT $+2

MOV AL, 8

OUT 21H,AL

JMP SHORT $+2

MOV AL,4

OUT 21H,AL JMP  SHORT $+2 MOV AL, 1

OUT 21H,AL JMP   SHORT $+2 ;второй контроллер

8-15 получают номера

MOV

AL,11H

OUT

OAOH,AL

JMP

SHORT $+2

MOV

AL,70H

OUT

0A1H,AL

JMP

SHORT $+2

MOV

AL, 2

OUT

0A1H,AL

JMP

SHORT $+2

MOV

AL,1

OUT

0A1H,AL

JMP

SHORT $+2

RETN

PROG_INTl

ENDP

/определение параметров видеосистемы WHAT_CRT  PROC NEAR

MOV AX,4OH

MOV ES,AX

MOV  BX,ES: [4AH]

MOV  COLUMNS,BL

MOV BL,ES:[84H]

INC BL

MOV ROWS,BL

MOV BX,ES:[63H]

CMP  BX,3D4H

JNE NO_COLOR адаптер

MOV   SEL_BUF,(GDT_CRT-GDTO)

MOV   SEG_BUF,OB800H

MOV ES,SEG_BUF

JMP  SHORT EXIT NO_COLOR:

MDA

MOV   SEL_BUF,(GDT_MDA-GDTO) MOV  SEG_BUF, 0B000H MOV ES,SEG_BUF

EXIT:

RETN

WHAT_CRT ENDP

;вывод на экран строки

;в ES либо селектор экрана, либо сегмент ;АХ,ВХ - X,Y

;SI - адрес строки ;АН - атрибут

WRITE   PROC NEAR /расчет смещения   в видеопамяти PUSH AX

MOV  DL,COLUMNS MUL DL ADD AX,BX SHL AX,1

MOV

POP AX

L01:

LODSB CMP AL, 0 JZ EN STOSW

JMP  SHORT L01

EN:

RETN

WRITE ENDP

/•обработка клавиатурного прерывания PROC NEAR

IN MOV

OR      AL,8 0H OUT 61H,AL XCHG AH,AL OUT 61H,AL

MOV OUT

RETN

END_INT ENDP

KEY  PROC NEAR

PUSH AX

;-конец прерывания

CALL END_INT POP AX IRET

KEYпрерывания таймера /вызывает звуковой сигнал,   примерно раз  в секунду

TIMER PROC NEAR

СЫ

MOV

OUT 20H,AL I RET

TIMER ENDP

прерываний от первого контроллера

INTl PROC NEAR PUSH AX

MOV AL,2 0H OUT 20H,AL

POP AX

MOV _DL,50

IRET INTl ENDP

прерываний от  второго контроллера

INT2 PROC NEAR PUSH AX

MOV AL,2 0H OUT 20H,AL OUT     OAH,AL

POP AX

MOV _DL,51

IRET INT2 ENDP

;обработка исключений

EXOO   PROC NEAR

MOV исключение JMP SET_REAL

EXOO ENDP EX0l PROC NEAR

MOV исключение

JMP SET_REAL EX0l ENDP

EX02   PROC NEAR

MOV исключение

JMP SET_REAL EX02 ENDP EX03 PROC NEAR

MOV исключение

JMP SET_REAL EX03 ENDP

ЕХ04   PROC NEAR

mov _DL, 5 6 ;4-e исключение

JMP SET_REAL ЕХ04 ENDP

ЕХ05   PROC NEAR

MOV _DL, 57 ; 5-е исключение

JMP SET_REAL ЕХ05 ENDP

EX06  PROC NEAR

MOV _DL, 58 ; 6-е исключение

JMP SET_REAL

ENDP

ЕХ07   PROC NEAR

MOV _DL, 5 9 ; 7-е исключение

JMP SET_REAL

ЕХ07 ENDP

ЕХ08   PROC NEAR

MOV _DL, 60 ;8-е исключение

JMP SET_REAL ЕХ08 ENDP

ЕХ09   PROC NEAR

MOV _DL, 61 ; 9-е исключение

JMP SET_REAL ЕХ09 ENDP

ЕХОА   PROC NEAR

MOV _DL, 62 ;AH-e исключение

JMP SET_REAL

ЕХОА ENDP

ехов   PROC NEAR

MOV _DL, 63 ; BH-e исключение

JMP SET_REAL ЕХОВ ENDP

ЕХОС   PROC NEAR

MOV _DL, 64 ;CH-e исключение

JMP SET_REAL ЕХОС ENDP

exod   PROC NEAR

MOV _DL, 65 ; DH-e исключение

JMP SET_REAL EXOD ENDP

ехое   PROC NEAR

MOV _DL, 66 ;.EH-e исключение

JMP SET_REAL

ЕХОЕ ENDP

EXOF PROC NEAR.

MOV _DL,67   ; FH-e исключение

JMP SET_REAL EXOF ENDP

EX10  PROC NEAR

MOV исключение

JMP SET_REAL EX10 ENDP

EX11  PROC NEAR

MOV исключение

JMP SET_REAL

EX11 ENDP EX12   PROC NEAR

MOV исключение

JMP SET_REAL

EX12 ENDP

EX13   PROC NEAR

MOV исключение

JMP SET_REAL EX13 ENDP

EX14   PROC NEAR

MOV исключение

JMP SET_REAL

EX14 ENDP

EX15  PROC NEAR

MOV исключение

JMP SET_REAL

EX15 ENDP

EX16   PROC NEAR

MOV исключение

JMP SET_REAL ENDP

EX17   PROC NEAR

MOV исключение

JMP SET_REAL

EX17 ENDP

EX18  PROC NEAR

MOV исключение

JMP SET_REAL

EX18 ENDP

EX 19   PROC NEAR "

MOV исключение

JMP SET_REAL

EX19 ENDP

ЕХ1А PROC NEAR

MOV _DL,78   ;1АН-е исключение

JMP SET_REAL EX1A ENDP

EX1B   PROC NEAR

MOV исключение

JMP SET_REAL

EX1B ENDP

EX1С  PROC NEAR

MOV   _DL,80   ;lCH-e исключение

JMP SET_REAL EX1C ENDP

EXID  PROC NEAR

MOV исключение

JMP SET_REAL EX1D ENDP

EX IE   PROC NEAR

MOV исключение

JMP SET_REAL EX1E ENDP

EXIF  PROC NEAR

MOV исключение

JMP SET_REAL EXIF ENDP PAUSE PROC

PUSH CX

MOV    CX,550 ■

PL:

PUSH CX

MOV CX,OFFFFH

PL1:

PL1

POP CX

LOOP PL

POP CX RETN

PAUSE ENDP

;сообщение об ошибке и  возврат  в реальный режим ;процедура инициализации   защищенного режима INI_PROT PROC

;заполнение таблицы прерываний ;заполнение GDT

MOV АХ, DATA MOV DS,AX MOV DL, AH SHR DL, 4 SHL AX, 4 MOV SI, AX MOV DI,DX

-дескриптор для GDT

ADD AX,OFFSET GDTO ADC DL, 0

MOV BX,OFFSET GDT_GDT MOV WORD  PTR   [BX] , OFFFFH MOV [BX+2],AX

MOV [BX+4],DL

MOV BYTE   PTR   [BX+5],DATA_AC

-дескриптор сегмента данных

MOV BX,OFFSET GDT_DS MOV AX,SI

MOV DX,DI

MOV WORD  PTR   [BX] , OFFFFH MOV [BX+2],AX

MOV [BX+4],DL

MOV BYTE   PTR    [BX+5] , DATA_AC

-дескриптор  сегмента кода

MOV BX,OFFSET GDT_CS MOV AX,CS MOV  DL, AH SHR  DL, 4 SHL AX,4

MOV    WORD  PTR   [BX], OFFFFH MOV [BX+2],AX

MOV [BX+4],DL

MOV BYTE   PTR    [BX+5] , CODE AC

MOV GDT_SS

MOV AX,SS

MOV DL,AH

SHR DL,4 ■'

SHL AX,4

MOV    WORD   PTR    [BX] , OFFFFH MOV [BX+2],AX

MOV [BX+4],DL

MOV BYTE   PTR    [BX+5] , DATA_AC

MOV ВХ,OFFSET GDTCRT MOV WORD PTR [BX],3999 MOV WORD PTR [BX+2], 8000H MOV BYTE PTR [BX+4],0BH MOV BYTE PTR   [BX+5],DATA_AC

MOV GDT_MDA

MOV WORD PTR [BX],3999 MOV BYTE PTR [BX+4],0BH MOV BYTE PTR  [BX+5],DATA_AC

-структура для таблицы прерываний

MOV ВХ,OFFSET GDT IDT MOV AX,DS MOV DL,AH SHR DL,4

SHL

ADD AX, OFFSET EXC OO ADC DL,0

MOV WORD  PTR    [BX] , IDT_SIZE-1

MOV WORD  PTR [BX+2],AX

MOV BYTE   PTR [BX+4],DL

MOV BYTE   PTR   [BX+5] , IDT_AC

-исключения

MOV EXOO

MOV BX,OFFSET EXC_00 MOV [BX],AX

MOV WORD  PTR   [BX+2],   (GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE   PTR    [BX+5] , TRAP AC

MOV AX,OFFSET EX01 MOV BX,OFFSET EXC_01 MOV [BX],AX

MOV WORD  PTR    [BX+2] , (GDT_CS-GDTO)

MOV BYTE PTR   [BX+4] , 0

MOV BYTE   PTR   [BX+5], TRAP AC

MOV EX02

MOV BX,OFFSET EXC_02 MOV [BX],AX

MOV WORD  PTR    [BX+2], (GDT_CS-GDTO)

MOV BYTE  PTR [BX+4],0

MOV BYTE   PTR    [BX+5] , TRAP AC

MOV AX, OFFSET EX03 MOV BX, OFFSET EXC_03 MOV [BX],AX

mov word  ptr    [bx+2], (gdt_cs-gdto)

mov byte   ptr [BX+4],0

mov byte  ptr    [BX+5] , TRAP_AC

mov AX,OFFSET ex04 mov BX,OFFSET exc_04 mov [BX],AX

mov word ptr   [bx+2]  , (gdt_cs-gdto)

mov byte   ptr [bx+4],0

mov byte  ptr    [BX+5] , TRAP AC

mov AX,OFFSET ex05 mov  BX,OFFSET exc_05 mov [BX],AX

mov word  ptr    [bx+2] , (gdt_cs-gdto)

mov byte   ptr [BX+4],0

mov byte  ptr    [BX+5], TRAP AC

mov

mov BX,OFFSET exc_06 mov [BX],AX

mov word ptr   [bx+2] , (gdt_cs-gdto)

mov byte   ptr [BX+4],0

mov byte   ptr    [BX+5], TRAP AC

mov AX,OFFSET ex07 mov BX,OFFSET exc_07 mov [BX],AX

mov word  ptr    [bx+2], (gdt_cs-gdto)

mov byte   ptr [BX+4],0

mov byte  ptr    [BX+5], TRAP AC

mov AX,OFFSET ex0 8

mov BX,OFFSET exc_0 8 ■ mov [BX],AX

mov word  ptr [bx+2], (gdt_cs-gdto)

mov BYTE. PTR [bx+4],0

mov byte  ptr [BX+5], TRAP AC

mov ex09

mov BX,OFFSET exc_0 9

mov

MOV WORD PTR [BX+2],(GDT_CS-GDTO)

MOV BYTE PTR [BX+4],0

MOV BYTE PTR [BX+5] , TRAP_AC

mov AX,OFFSET exoa MOV BX,OFFSET EXC_OA MOV [BX],AX

mov word ptr [bx+2] , (gdt_cs-gdto) —    MOV BYTE   PTR [BX+4],0

MOV BYTE   PTR   [BX+5], TRAP AC

mov exob

MOV BX,OFFSET EXC_0B MOV [BX],AX

MOV WORD  PTR    [BX+2],(GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

mov byte ptr

mov exoc

MOV BX,OFFSET EXC_OC MOV [BX],AX

mov word ptr

MOV BYTE   PTR    [BX+4],0 ■ MOV BYTE   PTR   [BX+5] , TRAP_AC

mov exod

MOV BX,OFFSET EXC_0D MOV [BX],AX

mov word  ptr   [bx+2], (gdt_cs-gdto)

MOV BYTE   PTR [BX+4],0

• MOV BYTE   PTR    [BX+5], TRAP AC

mov exoe

MOV BX,OFFSET EXC_OE MOV [BX],AX

mov word ptr   [bx+2]  , (gdt_cs-gdto)

MOV BYTE   PTR [BX+4],0

MOV BYTE  PTR    [BX+5] ,TRAP_AC

mov

MOV BX,OFFSET EXC_OF MOV [BX],AX

MOV WORD PTR [BX+2],   (GDT CS-GDTO)

MOV BYTE PTR

MOV BYTE PTR  [BX+5],TRAP AC

MOV EXlO

MOV BX, OFFSET EXCJO MOV [BX],AX

MOV WORD PTR   [BX+2]  ,   (GDT_CS-GDTO)

MOV BYTE PTR MOV BYTE PTR

MOV AX, OFFSET EX11

MOV BX,OFFSET EXC_11 . MOV [BX],AX

MOV WORD   PTR [BX+2]   , (GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE PTR

MOV EX12

MOV BX,OFFSET EXC_12

MOV

MOV WORD PTR [BX+2] , (GDT_CS-GDTO) MOV BYTE   PTR [BX+4],0

MOV BYTE PTR

MOV AX OFFSET EX13 MOV BX,OFFSET EXC_13 MOV [BX],AX

MOV WORD PTR MOV BYTE PTR

MOV BYTE   PTR   [BX+5], TRAP AC

MOV EX14

MOV

MOV

MOV WORD  PTR [BX+2]  ,   (GDT_CS-GDTO)

MOV BYTE PTR

MOV BYTE   PTR [BX+5] , TRAP_AC

MOV EX15

MOV BX,OFFSET EXC_15

MOV

MOV WORD   PTR    [BX+2] , (GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

mov AX,OFFSET EX16 mov BX, OFFSET EXC_16 mov [BX] ,AX

MOV WORD  PTR    [BX+2] , (GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE   PTR    [BX+5], TRAP AC

MOV

MOV BX,OFFSET EXC_17 MOV [BX],AX

MOV WORD   PTR    [BX+2] , (GDT_CS-GDTO)

MOV  BYTE   PTR [BX+4],0

MOV BYTE   PTR    [BX+5], TRAP AC

MOV EX18

MOV BX,OFFSET EXC_18

MOV

MOV WORD PTR' [BX+2],   (GDT_CS-GDTO)

MOV BYTE PTR (BX+4],0

MOV BYTE PTR [BX+5], TRAP AC

MOV AX,OFFSET EX19 MOV BX,OFFSET EXC_19 MOV [BX],AX

MOV WORD PTR [BX+2] , (GDT_C S - GDTO) MOV BYTE   PTR [BX+4],0

MOV BYTE PTR

MOV AX,OFFSET EX1A

MOV BX,OFFSET EXC_1A

MOV

MOV WORD  PTR    [BX+2], (GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE   PTR    [BX+5], TRAP AC

MOV EX1B

MOV BX,OFFSET EXC_1B MOV [BX],AX

MOV WORD  PTR [BX+2] ,   {GDT__CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE

MOV EXlC

MOV BX,OFFSET EXC 1С

MOV WORD  PTR [BX+2] , (GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE   PTR [BX+5] ,TRAP_AC

MOV AX,OFFSET EX1D MOV BX,OFFSET EXC_1D MOV [BX],AX

MOV WORD  PTR   [BX+2] ,   (GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE   PTR    [BX+5],TRAP AC

MOV EX1E

MOV BX,OFFSET EXC_1E MOV [BX],AX

MOV WORD PTR   [BX+2] ,   (GDT_C S - GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE  PTR   [BX+5], TRAP AC

MOV AX,OFFSET EXIF

MOV BX,OFFSET EXC_1F MOV [BX],AX

MOV WORD   PTR [BX+2],   <GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE  PTR [BX+5] ,TRAP_AC

--прерывания

MOV AX,OFFSET TIMER

MOV BX,OFFSET INT_20 MOV (BX],AX

MOV WORD PTR   [BX+2]  , (GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE   PTR [BX+5] , INTAC

MOV AX,OFFSET KEY MOV BX,OFFSET INT_21 MOV [BX],AX

MOV WORD PTR   [BX+2] , (GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE   PTR    [BX+5], I NT AC

MOV AX,OFFSET INT1

MOV BX,OFFSET INT_22 MOV [BX],AX

MOV WORD   PTR [BX+2],   (GDT_CS-GDTO)

MOV BYTE PTR [BX+5],INTAC

MOV AX,OFFSET INT1 MOV BX, OFFSET INT 23 MOV [BX] , AX

MOV WORD PTR   [BX+2],   (GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE   PTR    [BX+5],INT AC

MOV AX,OFFSET INT1 MOV BX,OFFSET INT_24 MOV [BX],AX

MOV WORD   PTR    [BX+2] , (GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE   PTR    [BX+5],INT AC

MOV INT1

MOV BX,OFFSET INT_25 MOV [BX],AX

MOV WORD PTR   [BX+2] , (GDT_CS-GDTO)

MOV BYTE  PTR [BX+4],0

MOV BYTE   PTR    [BX+5],INT AC

MOV INT1

MOV BX,OFFSET   INT_2 6 MOV [BX],AX

MOV WORD PTR   [BX+2] , (GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE   PTR    [BX+5],INT AC

MOV INT1

MOV BX,OFFSET   INT_2 7 MOV [BX],AX

MOV WORD PTR   [BX+2] , (GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE   PTR    [BX+5],INT AC

MOV INT2

MOV BX,OFFSET  INT_2 8 MOV [BX],AX

MOV WORD PTR   [BX+2] , (GDT_CS-GDTO)

MOV BYTE   PTR [BX+4],0

MOV BYTE   PTR [BX+5],INTAC

MOV

AX,OFFSET

INT2

MOV

BX,OFFSET

1 INT_29

MOV

[BX],AX

 

mov

word ptr

(gdt_cs-gdto)

mov

byte ptr

[BX+4],0

mov

ptr

[BX+5],INT_AC

mov

AX,OFFSET

int2

mov

BX,OFFSET

int_2a

mov

{BX],AX

 

mov

word ptr [

bx+2] , (gdt_cs-gdto)

mov

byte ptr

[BX+4],0

mov

byte ptr

[BX+5],INT_AC

mov

AX,OFFSET

int2

mov

BX,OFFSET

int_2b

mov

[BX],AX

 

mov

word ptr

[bx+2] , (gdt_cs-gdto)

mov

byte ptr

[bx+4],0

mov

byte ptr

[BX+5], INT_AC

mov

AX,OFFSET

int2

mov

BX,OFFSET

int_2c

mov

[BX],AX

 

mov

word ptr

[BX+2],(GDT CS-GDTO]

mov

byte ptr

[BX+4],0

mov

byte ptr

[BX+5],INT_AC

mov

AX,OFFSET

int2

mov

BX,OFFSET

int_2d

mov

[BX],AX

 

mov

word ptr

[bx+2] ,   (gdt_cs-gdto)

mov

byte ptr

[BX+4],0

mov

byte ptr

[bx+5],int_ac

mov

AX,OFFSET

int2

mov

BX,OFFSET

int_2e

mov

[BX],AX

 

mov

word ptr

[bx+2]  , (gdt_cs-gdto)

mov

byte ptr

[bx+4],0

mov

byte ptr

[BX+5],INTAC

MOV AX,OFFSET INT2 MOV BX, OFFSET INT_2F MOV [BX],AX

MOV WORD  PTR   [BX+2] , (GDT__CS-GDTO)

MOV  BYTE   PTR [BX+4],0

MOV BYTE   PTR   [BX+5]   , INT_AC

RETN INI_PROT ENDP ;процедура очистки экрана

/в ES находится либо селектор,   либо сегмент ■;в АН  - атрибут CLS PROC

mov СХ,2000

mov   AL,32

XOR    DI, DI

L2:

STOSW

LOOP L2

RETN CLS ENDP

CSEG_SIZE=$-BEGIN

CODE ENDS

END BEGIN

Рис. 20.4. Программа, реализующая вход в защищенный режим и выход из него средствами 386-го процессора.