Тема №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 Все права принадлежат авторам размещенных материалов.
|