Методическое руководство к курсовой работе по дисциплине Assembler ibm pc содержание

Вид материалаРуководство

Содержание


Proc new_09h
Endp new_09h Proc new_1Bh ;Новый обработчик прерывания по Ctrl-Break iret Endp new_1Bh Proc main
Endp main End main ;Конец программы/точка входа
Prg4. Запрет прерываний по Ctrl-C и Ctrl-Break (второй вариант)
Подобный материал:
1   2   3   4   5   6   7   8   9
^

Proc new_09h


;Новый обработчик вектора 09h

pusha ;Сохраним все регистры, включая сегментные регистры,

push es ;т.к. не знаем их значения на момент прерывания

push ds

mov ax,40h ;настроим предварительно ES на начало области

mov es,ax ;данных BIOS

in al,60h ;Введём скан-код из порта данных контроллера клавиатуры

jmp short $+2 ;Застрахуемся задержкой на ввод с периферии

cmp al,2Eh ;Скан-код клавиши "С"?

jnz handler09 ;Нет. Перейдём в системный обработчик 09h

;Отметим, что если будет нажата клавиша Ctrl вне комбинации Ctrl-C, то мы перейдём также в

;системный обработчик

test [byte es:17h],00000100b ;Да, нажата клавиша "С". Проверим статус

;клавиши Ctrl (2-й бит 1-го байта флагов клавиатуры)

jz handler09 ;Переход, если клавиша Ctrl не нажата

;Замечание. Мы не стали сбрасывать соответствующий бит в байте флагов, т.к. всё равно эту

;операцию надо было бы повторить и для второго байта флагов. Итак, продолжается участок

;программы, когда оказалось нажатой комбинация Ctrl-C. Разрешим дальнейшую работу контроллеру

;клавиатуры (стандартная процедура)

in al,61h ;Введём содержимое порта 61h

or al,80h ;Подтвердим приём кода, записав 1 в старший

out 61h,al ;бит порта 61h

and al,7fh ;Снова разрешим работу контроллера клавиатуры,

out 61h,al ;сбросив старший бит порта 61h

;Завершим работу системного контроллера обработки аппаратных прерываний

mov al,20h ;20h - команда EOI

out 20h,al ;20h - порт контроллера

pop ds ;Восстановим регистры

pop es

popa

iret

;Переход на системный обработчик. Ещё раз заметим, что клавиша Ctrl может быть нажата вне

;комбинации Ctrl-C

handler09: mov ax,@data ;Восстановим значение регистра ds,

mov ds,ax ;соответствующее сегменту данных) *См. комментарий

pushf

call [dword ds:old_09h] ;В системный обработчик с возвратом

pop ds ;Восстановим регистры

pop es

popa

iret
^

Endp new_09h

Proc new_1Bh


;Новый обработчик прерывания по Ctrl-Break

iret

Endp new_1Bh

Proc main


mov ax,@data ;Установка в ds адреса

mov ds,ax ;сегмента данных

;Сохраним системные вектора 09h и 1Bh с помощью функции 35h

mov ax,3509h ;al=09h- номер вектора

int 21h

mov [word old_09h],bx ;offset 09h

mov [word old_09h+2],es ;segment 09h

mov ax,351Bh ;al=1Bh- номер вектора

int 21h

mov [word old_1Bh],bx ;offset 1Bh

mov [word old_1Bh+2],es ;segment 1Bh

;Установим новые обработчики векторов 09h и 1Bh функцией 25h. Адрес обработчиков должен

;быть в DS:DX

mov ax,2509h ;al=09h- номер вектора

mov dx,offset new_09h

push ds ;Сохраним ds

mov bx,seg new_09h

mov ds,bx

int 21h

pop ds ;Восстановим ds

mov ax,251Bh ;al=1Bh- номер вектора

mov dx,offset new_1Bh

push ds ;Сохраним ds

mov bx,seg new_1Bh

mov ds,bx

int 21h

pop ds ;Восстановим ds

;Собственно программа пользователя

;Бесконечный цикл вывода на экран "*", выход из которого осуществляется нажатием

;клавиши ESC. В циклический процесс вывода введена небольшая задержка с целью

;обеспечения «мгновенной» реакции на нажимаемые клавиши. Нажатие комбинаций клавиш Ctrl-C и

;Ctrl-Break не прерывает цикл вывода "*" на консоль

loop1: mov dl,'*'

mov ah,02h

int 21h

mov cx,0

M1: loop M1 ;Небольшая задержка

mov ah,06h ;Функция ввода/вывода. Режим ввода задаётся

mov dl,0ffh ;значением dl=0ffh.

int 21h ;Возвращает: al=код символа и zf=0.

;При отсутствии символа в кольцевом буфере не ждёт его ввода, а устанавливает флаг zf=1 и

;передаёт управление программе

jz loop1

cmp al,27 ;ASCII- код клавиши ESC?

jnz loop1 ;Нет, цикл продолжится

;Выход из цикла, т.к. нажата клавиша ESC

;Восстановление старых (системных) обработчиков

mov ax, 2509h ;al=09h -номер вектора

lds dx,[old_09h] ;ds:dx - адрес вектора 09h

int 21h

mov ax, 251Bh ;al=1Bh -номер вектора

lds dx,[old_1Bh] ;ds:dx - адрес вектора 1Bh

int 21h

Exit: mov ax,4C00h ;Выходим в DOS

int 21h
^

Endp main

End main ;Конец программы/точка входа


Комментарий. Обратите внимание на окончание прикладного обработчика new_09h, где выбрана первая форма сцепления обработчиков

pushf

call [dword ds:old_09h] ;В системный обработчик с возвратом

Так как ячейка old_09h для хранения системного вектора хранится в сегменте данных программы, нам потребовалось восстановить то значения сегментного регистра DS, которое он имел после выполнения первой пары команд основной процедуры main, чтобы правильно сделать ссылку к памяти (ds:old_09h). Никаких других причин для использования сегментного регистра DS в данном обработчике нет. Ясно, что после этого нам нужно вернуться из системного обработчика, чтобы восстановить status quo.

Ниже представлены программа Prg4, в которой ячейки для хранения старых векторов расположены в сегментном коде основной программы (можно хранить и в программном коде обработчиков, главное не допустить исполнение кода данных в качестве команды процессора). В тексте программ Prg4 приведены полностью лишь те модули, в которых произошли изменения. Сравнительный анализ программ Prg3 и Prg4 позволит вам в дальнейшим избежать многих неприятностей с производством ссылок к памяти.

^ Prg4. Запрет прерываний по Ctrl-C и Ctrl-Break (второй вариант)

IDEAL

MODEL small

P486N

STACK 256

DATASEG

;Сегмент данных для основной программы (в данной задаче он пуст в силу особенностей основной

;программы, а. ячейки памяти для хранения векторов системных обработчиков мы разместили в

;программном коде основной программы)

CODESEG

;Новый обработчик вектора 09h

Proc new_09h

pusha ;Сохраним все регистры

push es ;Сохраним сегментный регистр ES

mov ax,40h ;Настроим предварительно ES на начало области



;Дальше, так же как в программе Prg3



handler09: pop es ;Восстановим регистры

popa

jmp [dword cs:old_09h] ;В системный обработчик без возврата

;old_09h DD ? ;одно из возможных мест хранения

Endp new_09h

;Новая процедура прерывания по Ctrl-Break

Proc new_1B

Iret

;old_1Bh DD ? ;одно из возможных мест хранения