Здавалка
Главная | Обратная связь

Тема №14 Задачи на обработчики прерываний



Цель занятия:Познакомиться с системными средствами распределения памяти, организацией дочерних процессов, научиться программировать, используя функции DOS (прерывание 21h), уметь работать с памятью.

 

Задания

Работа с таймером с помощью прерывания 1Ch. Написать программу, перехватывающую прерывания от системного таймера, поступающие каждые 18,2с., пересчитывающую их для уменьшения частоты и периодически выводящую на экран какую-либо информацию. В данном примере программа обработки прерываний от таймера включена в состав основной программы. При необходимости ее можно сделать резидентной.

;основные фрагменты программы

;сделаем в программе только два сегмента – программный и стек

myproc proc

;заполним вектор 1Ch адресом нашего обработчика прерываний

;от таймера

;сохранять адрес «программы-заглушки» BIOS нет необходимости, ;т.к. он известен из документации

mov ah,25h ;функция загрузки вектора

mov al,1ch ;тип вектора

lea dx,alarm ;смещение нашего обработчика

push cs ;отправим CS в DS

pop ds ;DS:DX->alarm

int 21h

;остановим программу, чтобы наблюдать работу таймера

;завершим программу.

;Сначала восстановим содержимое вектора 1Ch

;адрес «программы-заглушки» в ПЗУ BIOS известен

puch ds ;сохраним DS

mov dx,0ff53h ;смещение обработчика BIOS

mov ax,0f000h ;сегмент обработчика BIOS

mov ds,ax ;настроим DS

mov ax,251ch ;функция заполнения вектора

int 21h

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

;завершим программу обычным образом

;наш обработчик прерываний от таймера

alarm:

push ax ;сохраним все

push bx ;используемые

push es ;регистры

;регистр DS пришел к нам из программы BIOS

;поэтому адресуемся через CS

dec cs:count ;декремент счетчика времени

cmp cs:count,0 ;отсчитали 18 прерываний?

je output ;да, на вывод символа

jmp short retret ;нет, на выход

output:

dec cs:nmb ;декремент счетчика символов

cmp cs:nmb,0 ;все символы выведены?

je retret ;да, на выход

mov ax,cs:count1 ;заполним счетчик

mov cs:count,ax ;времени константой

mov ax,0b800h ;получим адресуемость

mov es,ax ;к видеобуферу

mov bx,cs:pos ;позиция символа

mov al,cs:sym ;символ

mov byte ptr es:[bx],al ;на экран его

inc bx ;инкремент позиции

mov byte ptr es:[bx],1fh ;атрибут

inc cs:sym ;инкремент символа (0,1…)

inc bx ;еще раз инкремент позиции

mov cs:pos,bx ;сохраним новую позицию

retret:

pop es ;восстановим

pop bx ;все

pop ax ;регистры

iret ;выход из обработчика

sym db ‘0’ ;выводимый символ

nmb db 10+1 ;число выводимых символов+1

count dw18 ;счетчик времени (1с)

count1 dw 18 ;константа счетчика времени

pos dw 80*2+60*2 ;позиция вывода на экран

1) Установка будильника реального времени. Прочитать из КМОП-микросхемы текущее время, прибавить к нему заданный интервал и установить будильник на полученное время. В программе обработке прерывания будильника вывести на экран символ.

;основные фрагменты программы

new_4ah proc ;наш обработчик прерывания будильника

push es ;сохраним

push ax ;используемые

push cx ;регистры

mov ax,0b800h ;настроим ES

mov es,ax ;на видеобуфер

mov es:2000,0f40fh ;выведем в центре экрана символ

pop cx ;восстановим

pop ax ;используемые

pop es ;регистры

iret ;выход из обработчика прерывания

new_4ah endp

;главная процедура

;сохраним вектор 4Ah

mov ax,354ah

int 21h

mov word tpr old_4ah,bx

mov word ptr old_4ah+2,es

;установим собственный обработчик прерывания 4Ah

mov ax,254ah

mov dx,offset new_4ah

push ds ;сохраним DS

push cs ;настроим DS

pop ds ;на сегмент команд

int 21h

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

;получим текущее время

mov ah,02h ;функция получения текущего времени

int 1ah

;прибавим время из поля time

mov si,offset hour

call add_time

;установим будильник

mov ah,06h ;функция установки будильника

;регистры ch, cl, dh уже настроены

int 1ah

;остановим программу вызовом функции DOS ввод символа

;с клавиатуры

;сбросим будильник

mov ah,07h

int 1ah

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

mov ax,254ah

push ds

lds dx,old_4ah

int 21h

pop ds

;завершим программу

;поля данных программы

hour db 0 ;задаваемый интервал

min db 0 ;времени перед срабатыванием

sec db 5h ;будильника

old_4ah dd 0 ;ячейка для хранения вектора 4Ah

;подпрограмма сложения трех разрядов времени (часов, минут и ;секунд)

;в двоично-десятичном формате

add_time proc

;при вызове: исходное время: ch=часы, cl=минуты, dh=секунды (в ;BCD)

;прибавляемое время в массиве из трех байтов: часы, минуты,

;секунды (в BCD), адрес массива в DS:SI

;при возврате в тех же регистрах результат сложения в том же

;формате

push ax ;сохраним

push bx ;используемые

push di ;регистры

mov di,1 ;подготовим 1 для переноса

;сложим секунды

mov al,dh ;исходные секунды отправим в AL

mov bl,[si+2] ;получим прибавляемые секунды

mov bh,k0 ;и в виде слова

push bx ;отправим в стек

call add_unit ;вызов подпрограммы сложения

mov dh,al ;результат назад в DH

jnc mmm ;переноса нет, на сложение минут

;перенос. Прибавим 1 к минутам

mov al,cl ;исходные минуты отправим в AL

push di

;прибавляемую 1 в стек

call add_unit ;вызов подпрограммы сложения

mov cl,al ;результат назад в CL

jnc mmm ;переноса нет, на сложение минут

;перенос, прибавим 1 к часам

mov al,ch ;исходные часы отправим в AL

push di ;прибавляемую 1 в стек

call add_unit ;вызов подпрограммы сложения

mov ch,al ;результат назад в СН

;сложим минуты

mmm:

mov al,cl ;исходные минуты отправим в AL

mov bl,[si+1] ;получим прибавляемые минуты

mov bh,0 ;и в виде слова

push bx ;отправим в стек

call add_unit ;вызов подпрограммы сложения

mov cl,al ;результат назад в CL

jnc hhh ;переноса нет, на сложение часов

;перенос, прибавим 1 к часам

mov al,ch ;исходные часы отправим в AL

push di ;прибавляемую 1 в стек

call add_unit ;вызов подпрограммы сложения

mov ch,al ;результат назад в СН

;сложим часы

hhh:

mov al,ch ;исходные часы отправим в AL

mov bl,[si] ;получим прибавляемые часы

mov bh,0 ;и в виде слова

push bx ;отправим в стек

call add_unit ;вызов подпрограммы сложения

mov ch,al ;результат назад в СН

;восстановим используемые регистры

pop di

pop bx

pop ax

ret

add_time endp

;подпрограмма сложения одного разряда времени

add_unit proc

;при вызове: al=время в BCD (секунды, минуты или часы)

;младший байт верхнего слова стека – прибавляемая величина

;(секунды, минуты или часы), при возврате: al = результат

;сложения в BCD, АН разрушен

push bp ;сохраним

push bx ;используемые регистры

mov ah,0 ;подготовим АН

mov bp,sp ;настроим базовый регистр

mov bx,[bp+6] ;получим параметр

add al,bl ;сложим слагаемые

daa ;как BCD

jnc less100 ;сумма меньше 100

mov ah,1 ;сумма больше 100, запишем 01h в AH

less100: ;надо ли корректировать

cmp ax,60h ;следующий разряд времени

jb done ;нет, сумма < 60

sub ax,60h ;да, сумма > 60, вычтем 60

das ;как BCD

stc ;установим CF, как признак переноса

jmp done1 ;и на выход

done: clc ;сбросим CF

done1:

pop bp ;восстановим используемые

pop bx ;регистры

ret 2 ;скорректируем указатель стека

add_unit

Вопросы для самоконтроля

1. Назовите функцию заполнения вектора.

2. С помощью какого регистра можно установить декремент счетчика времени.

3. Назовите функцию смещения обработчика BIOS.

4. Назовите функцию загрузки вектора.

5. Назовите сегмент обработчика BIOS.








©2015 arhivinfo.ru Все права принадлежат авторам размещенных материалов.