In_mem : mov al,0fFh ;Занесение признака 'Программа уже
iret ;установлена' и выход из прерывани
;------------------------------ ;Начало программы выгрузки
unset1: push DS ;Сохраним те регистры,
push ES ;содержимое которых
push DX ;меняется в программе
mov AX,252Fh ;Восстановим вектор 2Fh
lds DX,CS:old_2f
int 21h
;Получим из PSP адрес собственного окружения и выгрузим его
mov ES,CS:[2Ch] ;Занесение из PSP:2Ch адреса
mov AH,49h ;окружения в рег. ES и выгрузка
int 21h ;блока окружения
;------------------------Выгрузим саму программу
push CS ;Загрузим в ES содержимое CS,
pop ES ;т.е. сегментный адрес PSP
mov AH,49h ;Функция освобождения блока памяти
int 21h
pop DX ;Восстановление
pop ES ;используемых
pop DS ;регистров
iret ;Возврат из прерывания
;--------------Обработчик прерывания 09h------------------------
M2:
push ax ; Сохранение используемых регистров
push bx
push cx
push dx
push ds
push es
push si
PUSH CS
POP DS
in AL, 60h ;Введем скан-код
cmp AL,22h ;Скан-код 'G'?
je go1 ;Да, на продолжение анализа
exit1: pop si
pop es
pop ds
pop dx
pop cx
pop bx
pop AX ;Нет, восстановим регистр
jmp CS:old_09 ; и в системный обработчик
go1: push ES ;Сохраним используемый регистр
mov AX, 40h ;Настроим ES на начало
mov ES, AX ; области данных BIOS
mov AL, ES:[17h] ;Получим слово флагов клавиатуры
pop ES ;Восстановим ES - он больше не нужен
cmp AL, 0100b ;Уже нажата <Ctrl>?
je go ;Да, на выход в прерванную программу
jmp exit1 ;Нет, в системный обработчик
go:
mov si, offset s_byte
out1: ; вывод на экран строки
lodsb ; загрузка байта из DS:SI в AL
cmp al,'$' ; конец строки ?
je next2 ; если да, то дальше
mov ah,0eh
Int 10h ; вывод символа из al на экран
jmp out1 ; следующий символ
next2:
mov ax,40h
mov ds,ax
mov cx,8
mov dx,ds:[17h] ; чтение байта статуса клавиатуры
out2: test dx,10000000b ; последовательный вывод со сдвигом
je mzero ; вывод на экран
mov al,'1'
jmp out3
mzero: mov al,'0'
out3: mov ah,0eh
