- •Лучший курс лекций по лучшему языку программирования – языку ассемблера Блок управления памятью (mcb)
- •Программирование на Ассемблере для ibm pc
- •Программная модель 8086
- •Программная модель мп
- •Сегментная память
- •Вывод на экран
- •Вывод строки символов
- •Вывод на экран шестнадцатеричного числа
- •Процедуры
- •Ввод символов
- •Вывод на экран двоичного числа
- •Работа с дисковыми файлами
- •Префикс сегмента программы (psp)
- •Структура префикса программного сегмента.
- •Прерывания.
- •Табличные вызовы подпрограмм.
- •Макрокоманды.
- •Макроопределения.
- •Использование параметров в макроопределениях.
- •Директива local
- •Использование библиотек макроопределений.
- •Конкатенация. (&)
- •Директивы повторения.
- •Условные директивы.
- •Перечисление условных директив.
- •Пример использования ifnb.
- •Пример использования макроопределений.
- •Резидентные программы tsr (terminate and stay resident)
- •Защита резидентной программы от повторной загрузки.
- •Выгрузка резидентной программы.
- •Переключение стека в резидентной программе.
- •Обработчик прерываний от таймера
- •Контроллер прерываний и его программирование
- •Взаимодействие прикладных и системных обработчиков прерываний
- •Резидентный обработчик прерываний от клавиатуры с подключением до системного
- •Резидентный обработчик прерывания от клавиатуры с подключением после системного обработчика
- •Резидентный обработчик прерываний от клавиатуры с подключением как до, так и после системного.
- •Вывод на экран текста средствами bios
- •Режимы дисплея
- •Работа с видеобуфером.
- •Логическая организация текстового видеобуфера.
- •Программирование портов. Звук.
- •Программирование звукового канала таймера.
- •Интерфейс с Си
- •Программы с несколькими сегментами команд.
- •Программы с несколькими сегментами данных.
- •Директива assume. Инициализация сегментных регистров и замена сегментов.
- •Структуры и записи.
Резидентный обработчик прерываний от клавиатуры с подключением как до, так и после системного.
Иногда удобно некоторую часть обработки выполнить до системного обработчика, а некоторую часть после.
При получении управления, наш обработчик запоминает в ячейке tail содержимое хвостового указателя. Затем управление передается в системный обработчик. После возврата из системного обработчика, сохраненное содержимое хвостового указателя сравнивается с текущим значением, полученным из ячейки 40h:1Ch. Если системный обработчик не сместил хвостовой указатель, это значит, что была нажата какая-то управляемая клавиша (Shift),(Alt) и т.д. В этом случае необходимость в дальнейшем анализе отсутствует. Если указатель сместился, то в буфер был введен очередной код, который, очевидно, помещен в буфер по адресу, сохраненному в ячейке tail.
Таким образом, предыдущая программа написана не совсем корректно. В ней не рассматривалась возможность наличия управляемых клавиш, которые ничего не заносят в буфер. Нажатие управляемых клавиш приведет к тому, что предыдущая программа снова проанализирует предыдущий символ, который скорее всего был проанализирован ранее. Правда, такой повторный анализ не приведет к ошибке.
Если использовать в резидентной программе регистр DS, то каждая команда с адресацией к памяти получается на один байт короче, т.к. будет отсутствовать байт префикса замены регистра.
CODE_SEG SEGMENT
ASSUME CS:CODE_SEG,DS:code_seg
ORG 100H
START:
JMP BEGIN
int_2Fh_vector DD ?
old_09h DD ?
tail DW 0
;=============================================================================
;
;=============================================================================
new_09h proc far
push AX
push ES
mov AX,40h ; Настроим ES на сегментный
mov ES,AX ; адрес области данных BIOS
mov AX,ES:[1Ch] ; Сохраним адрес хвоста перед обработкой
mov CS:tail,AX
pop ES
pop AX
pushf ; В системный обработчик
call CS:old_09h ; с возвратом
push AX
push BX
push ES
mov AX,40h ; Настроим ES на сегментный
mov ES,AX ; адрес области данных BIOS
mov BX,CS:tail ; Адрес нового хвоста
cmp BX,ES:[1Ch] ; Хвост сместился?
je go_out ; нет – на выход
mov AX,ES:[BX] ; Получим последний символ из буфера
cmp AX,1600h ; Был введен расширенный код ASCII сочетания Alt/U?
jne go_out ; Нет
mov word PTR ES:[BX],OODAh ; Да, заменим код в буфере на код уголка
go_out:
pop ES
pop BX
pop AX
iret
new_09h endp
;=============================================================================
;
;=============================================================================
int_2Fh proc far
cmp AX,OC700h
jne pass_2Fh
mov AL,OFFh
iret
pass_2Fh:
jmp dword PTR CS:[int_2Fh_vector]
int_2Fh endp
;=============================================================================
;
;=============================================================================
begin:
mov AX,OC700h ; AH=OC7h номер процесса C7h
; AL=OOh -дать статус установки процесса
int 2Fh ; мультиплексное прерывание
cmp AL, 0
jz not_installed ; возвращает AL=0 если не установлена
lea DX,msg
call print
int 20h
msg DB 'Уже установлена',13,10,'$'
not_instailed:
mov AX,352Fh ; получить вектор
int 21h ; прерывания 2Fh
mov word ptr int_2Fh_vector,BX ; ES:BX - вектор
mov word ptr int_2Fh_vector+2,ES
mov DX,offset int_2Fh ; получить смещение точки входа в новый
; обработчик на DX
mov AX,252Fh ; функция установки прерывания
; изменить вектор 2Fh
int 21h ; AL - номер прерыв. DS:DX - указатель программы обработки прер.
mov AX,3509h ; получить вектор
int 21h ; прерывания 09h
mov word ptr old_09h,BX ; ES:BX - вектор
mov word ptr old_09h+2,ES ;
mov DX,offset new_09h ; получить смещение точки входа в новый
; обработчик на DX
mov AX,2509h ; функция установки прерывания
; изменить вектор 09h
int 21h ; AL - номер прерыв. DS:DX - указатель программы обработки прер.
;------------------------------------------------------------------------------
mov DX,offset begin ; оставить программу ...
int 27h ; ... резидентной и выйти
;=============================================================================
;
;=============================================================================
PRINT PROC NEAR
MOV АН,09H
INT 21H
RET
PRINT ENDP
;=============================================================================
CODE_SEG ENDS
END START
В командах, где обращение выполняется по абсолютному адресу, необходимо указывать обозначение сегментного регистра. Так, командуя
mov AX,1ch
засылает в АХ число 1сh (квадратные скобки не определяют косвенную адресацию), в то время, как, командуя
mov AX DS: 1ch
загружает в АХ содержимое слова памяти расположенного по адресу DS:1ch.
Указание регистра DS в программной строке не приводит к добавлению к коду команды префикса замены сегментного регистра, так как все команды с обращением к памяти по умолчанию используют для адресации именно регистр DS.