Создание TSR программ в операционной, страница 5

Этот модуль будет устанавливаться на прерывание 1Сh , поэтому дадим ему имя:

New_1C Proc

cmp cs:Cnt,182       ;проверяем прошло ли 10 сек.?

jb     M2                   ;если нет, то переход на увеличение счетчика

;(jb -переход при анализе беззнаковых величин)

mov cs:flg_timer,1  ;сообщение можно выводить, поэтому установим в

;ячейке флага истечения контрольного времени  1

M2:        inc   byte ptr cs:Cnt     ;увеличить счетчик времени на 1

jmp  cs:[Old_1С]     ;и перейти по адресу старого обработчика

;прерывания 2F.

Old_1С  DD   0                      ; это место под адрес старого обработчика преры;вания 2F.

Cnt        DB   0                      ;ячейка для счетчика тиков

flg_timer DB  0                      ;ячейка для флага истечения заданного времени

New_1С  endp

Обратите внимание, что при написании резидентной части TSR программ ячейки, используемые в программе, надо писать с приставкой сегмента CS (cs:Cnt, cs:flg_timer) тогда при передаче управления к Вашей программе от прерванной программы не возникнет неоднозначности в адресации (если Вы не напишите приставки CS, то машина «будет думать», что адресоваться надо относительно сегмента данных DS, а при передаче управления DS остается старым – той программы, которая была прервана Вами).

Модуль активизации и печати сообщения

Этот модуль будет устанавливаться на прерывание 28h , поэтому дадим ему имя:

New_28 proc

;В первую очередь сохраним регистр флагов процессора, потому что сейчас

;будем проводить проверку на истечение заданного времени, что изменит

;регистр флагов

pushf

;теперь проверим – в ячейке флага контроля истечения заданного времени

;установлена  единица?

cmp cs:flg_timer,1

;если нет, то время до вывода сообщения на экран еще не истекло и мы перехо;дим на старый обработчик прерывания 28h

jne M1

;в противном случае активизируем модуль вывода сообщения на экран. Для чего

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

;мы испортим в них данные прерванной нами программы.

push  ax

push  bx

push  bp

push  es

push  сх

;Запретим прерывания нашей программы другими программами

cli

;Внесем в регистр ES  адрес начала видеопамяти ПЭВМ.  Для тех, кто подзабыл

; – обратитесь к справочнику TECH HELP там указано, что видеопамять начинается

;с сегмента 0B800h. Поскольку сразу число в регистр ES занести нельзя, восполь;зуемся регистром BX как промежуточным буфером

mov   bx,0B800h

mov   es,bx

;Теперь загрузим смещение адреса выводимой текстовой строки в регистр BP

;(можно было – в любой другой, который может использоваться в качестве

;регистра смещения, например si или di, но нам понравился BP)

lea     bp,curtime

;Регистр BX выберем в качестве регистра смещения индекса буквы на экране

;и занесем в него начальное значение 0       

mov   bx,0

;установим счетчик для цикла в 19 (по количеству букв в выводимой строке curtime)

mov   cx,19                      

;Пометим начало цикла вывода строки текста на экран меткой vivod_on

vivod_on:

;Возьмем из строки текста, подготовленного нами для вывода, первую букву

mov   al,byte ptr cs:[bp]

;и поместим ее на экран в первую экранную текстовую ячейку

mov  byte ptr es:[bx],al   

;увеличим смещение BX на единицу, чтобы перейти к байту атрибутов текста на

;экране. Известно, что каждый символ текста на экране занимает в видеопамяти

;ПЭВМ два байта (слово). Младший байт хранит код самого символа, а старший –

;его цвет и цвет его фона (см. TECH HELP).

inc     bx

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

;(кодировка цвета символа и его фона тоже см. в TECH HELP).

mov   al,74h                     

mov   byte ptr es:[bx],al

;Увеличим счетчик букв на экране на 1        

inc     bx

;Увеличим счетчик букв в выводимой текстовой строке тоже на 1

inc     bp                           

;Повторим цикл для вывода следующего символа

loop   vivod_on

;После вывода всей строки, сбросим флаг готовности таймера и его счетчик,

;чтобы начался новый отсчет времени

movcs: flg_timer, 0

movcs:cnt, 0

;разрешим внешние прерывания

sti

;и восстановим все сохраненные регистры ОБЯЗАТЕЛЬНО в обратной последова;тельности их запоминания