;Берем из таблицы векторов прерываний текущий адрес INT 01h
mov ax,3501h
int 21h
mov si,bx ;смещение сохраняем в регистре SI
mov di,es ;сегмент сохраняем в регистре DI
;Устанавливаем свой обработчик INT 01h
mov ax,2501h
mov dx,offset Int01
int 21h
;Формируем в стеке адрес выхода из трассировки так, чтобы по IRET
;из INT 21h попасть на метку Next – помещаем в стек
;последовательно флаги, сегмент и смещение метки Next
pushf
push cs
mov ax,offset Next
push ax
;Начинаем трассировку INT 21h. Для этого нужно подготовить стек
;следующим образом: поместить в него флаги с включенным флагом
;трассировки, а также сегмент и смещение текущего обработчика
;INT 21h. Затем можно выполнить команду IRET – программа запустит
;текущий обработчик и считает из стека флаги (флаг трассировки
;во флаговом регистре включится, начнется трассировка. После
;каждой команды процессора будет запускаться INT 01h).
;Помещаем в стек флаги, включаем в них бит, соответствующий
;флагу трассировки TF. Для того, чтобы включить флаг
;трассировки TF, после сохранения флагов в стеке считаем их
;в регистр AX, в нем включим соответствующий бит, а затем
;сохраним регистр AX в стеке
pushf
pop ax
or ax,0100h
push ax
;Считаем из таблицы векторов прерываний текущий адрес INT 21h
mov ax,3521h
int 21h
;Сохраним в стеке сегмент, а затем и смещение текущего обработчика
push es
push bx
;Установим в регистре AH номер какой−либо безобидной функции
;(чтобы определение адреса обработчика DOS
;не сопровождалось разрушениями)
mov ah,0Bh
;Запускаем трассировку
cli
iret
;Обработчик INT 01h
Int01:
;При вызове обработчика в стеке находятся: значение регистра IP,
;значение регистра CS, флаги перед прерыванием.
;Адресуемся к стеку с помощью регистра BP,
;предварительно сохранив текущее значение BP
push bp
mov bp,sp
;Теперь в стеке находятся:
;SS:[BP] – BP
;SS:[BP+2] – IP
;SS:[BP+4] – CS
;SS:[BP+6] – флаги
;Проверяем флаг продолжения
cmp byte ptr cs:ContinueFlag,1
;Если флаг продолжения выключен, то выходим из трассировки
jne TraceOff
;Проверяем текущий адрес. Если сегмент меньше 300h,
;обработчик DOS достигнут, иначе – продолжаем трассировку
;и выходим из обработчика
cmp word ptr [bp+4],300h
jnc ExitFromInt
;Достигнут DOS – берем из стека адрес обработчика и сохраняем его
push bx
mov bx,[bp+2]
mov word ptr cs:O21,bx
mov bx,[bp+4]
mov word ptr cs:S21,bx
pop bx
;Заканчиваем обработку прерывания и дальнейшую трассировку
TraceOff:
;Устанавливаем в ноль бит, соответствующий TF,
;в копии регистра флагов в стеке
and word ptr [bp+6],0FEFFh
;Устанавливаем в ноль флаг продолжения
mov byte ptr cs:ContinueFlag,0
ExitFromInt:
pop bp
;Выходим из обработчика
iret
;Восстановление после трассировки
Next:
;Сбрасываем флаг продолжения
mov byte ptr ds:ContinueFlag,0
;Восстанавливаем прежнее значение вектора прерывания INT 01h
mov ax,2501h
mov dx,si
mov ds,di
int 21h