Поддержка процедур обработки прерываний
При написании процедур обработки прерываний существенными являются два обстоятельства. Во-первых, процедура обработки прерывания не должна искажать работу прерванной программы. Для этого необходимо сначала сохранить регистры центрального процессора, а перед выходом из процедуры - восстановить их. Во-вторых, процедура должна строиться по принципу реентерабельности (повторной входимости): ее работа может быть прервана в любой момент другими прерываниями и ДОС может обратиться к соответствующей функции до завершения обработки предыдущего прерывания.
Турбо Паскаль предоставляет программисту возможность написания процедур обработки прерывания на языке высокого уровня, хотя обычно такие процедуры пишутся на языке ассемблера.
Процедура обработки прерывания, написанная на Турбо Паскале, должна начинаться стандартной директивой INTERRUPT (прерывание), например:
Procedure IntProc (Flags, CS, IP, AX, BX, CX, DX,
SI, DF, DS, ES, BP : word); inerrupt;
begin
...
end ;
Формальные параметры в заголовке процедуры должны перечисляться в указанном порядке - через эти параметры все регистры прерванной программы становятся доступны процедуре обработки прерывания. Количество перечисляемых в заголовке процедуры параметров-регистров может быть любым, но не больше 12. Если в списке опущен какой-либо параметр, должны быть опущены также и все предшествующие ему параметры. Например, описание
Procedure IntProc(SI, DP, ES: word); interrupt;
будет неверным (опущены параметры DS и ВР); правильное описание:
Procedure IntProc(SI, DP, DS, ES, BP: word); interrupt;
Заметим, что компилятор не контролирует порядок перечисления параметров в заголовке процедуры обработки прерывания.
Директива INTERRUPT вызывает генерацию специальных машинных кодов, обеспечивающих заталкивание регистров в стек при входе в процедуру и извлечение их из стека перед выходом из нее.
При входе в процедуру:
push |
ax |
|
push |
bx |
|
push |
cx |
|
push |
dx |
|
push |
si |
|
push |
di |
|
push |
ds |
|
push |
es |
|
push |
bp |
|
mov |
bp, |
si |
sub |
sp, |
LocalSize |
mov |
ax, |
SEG DATA |
mov |
ds, |
ax |
При выходе из процедуры:
mov sp, bp
pop bp
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
irep
В самой процедуре обработки прерывания не рекомендуется обращаться к другим функциям ДОС, так как некоторые из них, в том числе все функции ввода-вывода, нереентерабельны.
Для связи с любыми процедурами прерываний, а следовательно, и с процедурами, написанными программистом, используются векторы прерываний - четырехбайтные абсолютные адреса точек входа в эти процедуры. Векторы прерываний располагаются в младших адресах оперативной памяти, начиная с нулевого адреса: прерывание номер 0 - по адресу 0, номер 1 - по адресу 1*4 = 4, номер N - по адресу N * 4. С помощью следующих двух процедур программист может прочитать содержимое любого вектора или установить его новое значение.
Процедура GETINTVEC.
Возвращает вектор прерывания с указанным номером. Обращение:
GETINTVEC (<,<вектор>)
Здесь <D> - выражение типа BYTE; номер прерывания;
<вектор> - переменная типа POINTER; адрес точки входа в процедуру обработки прерывания.
Представленная в примере 11.3 программа выводит на экран содержимое всех ненулевых векторов прерываний.
Пример 11.3
Uses DOS;
var
i : byte; p : pointer;
begin
for i := 0 to 255 do
begin
GetlntVec (i, p) ;
if (Seg (р) <> 0) or (Ofs (рл) <> 0) then
WriteLn (' N=', i:3, ' Seg=', Seg (р):5,
' Ofs =' , Ofs (р) :5)
end
end.
Процедура SETINTVEC.
Устанавливает ндвое значение вектора прерывания. Формат обращения:
SETINTVEC (<,<адрес>)
Здесь <D> - выражение типа BYTE; номер прерывания;
<адрес> - выражение типа POINTER; адрес точки входа в процедуру обработки прерывания.
При нормальном завершении программы она выгружается из памяти, что делает невозможным разработку резидентных в памяти процедур обработки прерываний. Вы можете прекратить работу программы и оставить ее резидентной в памяти, если воспользуетесь процедурой KEEP.
Процедура KEEP.
Завершает работу программы и оставляет ее резидентной в памяти. Обращение:
KEEP (<код>)
Здесь <код> - выражение типа WORD - код завершения программы. Код завершения представляет собой фактически единственный механизм передачи сообщений от запущенной программы к программе, которая ее запустила. Он может быть проанализирован в вызывающей программе с помощью функции DOSEXITCODE.
Функция DOSEXITCODE.
Возвращает значение типа WORD - код завершения подчиненной программы. Обращение:
DOSEXITCODE