Использование средств 32-разрядных процессоров в программировании
Пример 4.1. Чтение и сравнение системного времени по прерываниям от таймера.
0.586; Будут 32-разрядные операнды assume CS: code, DS:code code segment use16; 16-разрядное приложение org 100h; Формат. COM main proc ;Сохраним исходный вектор mov AX,3508h int 21h mov word ptr old_08,BX mov word ptr old_08+2,ES ;Установим наш обработчик mov AX,2508h mov DX,offset new_08 int 21h ;Прочитаем системное время, прибавим требуемый интервал ;и сохраним в двухсловной ячейке памяти mov AX,40h; Настройка ES на mov ES,AX; область данных BIOS mov EAX, ES: 6Ch; Получаем системное время add EAX,time_int; Прибавить интервал mov time_end,EAX; Сохраним в памяти ;Имитация рабочего цикла программы с опросом флага again: test flag,0FFh; Проверка флага готовности jnz ok; Если установлен, на OK mov АН,02h; В ожидании окончания mov DL,'.'; временного интервала int 2 In; выводим на экран точки jmp again; И снова на проверку флага ok: mov АН,09h; Интервал завершен. mov DX,offset msg; Выполним, что хотели int 2 In ;Завершим программу, восстановив сначала исходный вектор lds DX,old_08 mov AX,2508h int 21h mov AX,4C00h int 21n main endp ;Наш обработчик прерываний от системного таймера new_08 proc pushf; Запишем флаги в стек call CS:old_08; и вызовем системный обработчик push EAX; Сохраним используемые push ES; регистры mov AX,40h; Настроим ES mov ES,AX; на область данных BIOS mov EAX,ES:6Ch; Прочитаем текущее время cmp EAX,CS:time_end; Сравним с вычисленным jb ex; Если меньше, на выход inc CS:flag; Интервал истек, установим флаг ex: mov AL,20h; Команда конца прерывания out 20h,AL; в контроллер прерываний pop ES; Восстановим pop EAX; сохраненные регистры iret; Выход из обработчика new_08 endp ;Поля данных программы old_08 dd 0; Для хранения исходного вектора time_int dd 18*2; Требуемый интервал (~2с) time_end dd 0; Момент истечения интервала flag db 0; Флаг истечения интервала msg db "Время истекло!$'; Информационное сообщение code ends end main
Организация программного комплекса с обработчиком прерываний от системного таймера уже рассматривалась в примере 3.3 в гл. 3. Установка обработчика в рассматриваемом примере выполняется немного проще, так как нет необходимости настраивать регистр DS на сегмент данных – он и так уже настроен на единственный сегмент программы. Установив обработчик, программа настраивает регистр ES на область данных BIOS и считывает из ячейки с адресом 46Ch текущее системное время командой add к нему прибавляется заданный в ячейке time_int интервал (в примере – приблизительно 2 с), и результат сохраняется в ячейке timc_cnd.
Действия по установке обработчика закончены, и программа может приступить к выполнению запланированных для нее действий. В данном примере программа в цикле вызывает функцию DOS 02h вывода на экран символа точки; в действительности она может, например, выполнять обработку и вывод на экран некоторых данных. В каждом шаге цикла происходит тестирование флага окончания временного интервала flag, который должен быть установлен обработчиком прерываний по истечении заданного временного интервала. Пока флаг сброшен, цикл продолжается. Как только флаг окажется установлен, программа приступает к выполнению действий по отработке этого события. В рассматриваемом примере выполняется вывод на экран информационного сообщения и завершение программы с обязательным восстановлением исходного содержимого вектора 8.