Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Финогенов-основы_языка_ассемблера.doc
Скачиваний:
46
Добавлен:
17.09.2019
Размер:
3.35 Mб
Скачать

3.5. Двоично-десятичные числа

В гл. 2 уже говорилось о двоично-десятичных числах — специальном формате хранения данных, используемом в ряде технических приложе-;-ний. Часто эти числа называют BCD-числами (от binary-coded decimal, 'двоично-кодированные десятичные числа). Для обработки BCD-чисел (сло-^жения, вычитания, умножения и деления) в МП 86 предусмотрены спе­циальные команды. Рассмотрим этот вопрос на комплексном примере • обработки показаний КМОП-часов реального времени.

140 Главаз

Как известно, в современных компьютеров имеются два независимых таймера. Один из них («часы реального времени») включен в состав мик­росхемы с очень низким потреблением тока, питается от батарейки или аккумулятора, находящегося на системной плате, и работает даже на вык­люченной из сети машине. В этом таймере хранится и автоматически на­ращивается текущее календарное время (год, месяц, день, час, минута и секунда).

После включения компьютера вступает в работу другой таймер, кото­рый обычно называют системным. Датчиком сигналов времени для него служит кварцевый генератор, работающий на частоте 1,19318 МГц; сиг­налы от которого, после пересчета в отношении 65536:1, поступают в контроллер прерываний и инициируют прерывания через вектор 8 с час­тотой 18,2065 Гц. Эти прерывания активизируют программу BIOS, перио­дически выполняющую инкремент содержимого четырехбайтовой ячейки памяти с текущим временем, находящейся по адресу 46Ch. После включе­ния машины программы BIOS считывают из часов реального времени текущее время суток, преобразуют его в число тактов системного таймера (т.е. в число интервалов по 1/18,2065 с) и записывают в ячейку текущего времени. Далее содержимое этой ячейки наращивается уже системным таймером, работающим в режиме прерываний.

Для определения текущего времени прикладная программа может вызвать соответствующие функции прерывания 21h DOS (конкретно, с номером 2Ah для получения даты и 2Ch для получения времени суток), а может прочитать время непосредственно из часов реального времени с помощью прерывания lAli BIOS. При этом прерывание lAli позволяет, помимо чтения текущего времени (функция 02h) и текущей даты (функ­ция 04h), выполнять и целый ряд других функций, среди которых мы отметим только возможность установить «будильник», т.е. записать в мик­росхему часов значение календарного времени, когда часы должны вы­дать сигнал аппаратного прерывания. Этот сигнал через вектор 70h ини­циирует обработчик прерываний, входящий в состав BIOS, который про­веряет, возникло ли данное прерывание в результате достижения времени установки будильника (часы реального времени могут инициировать пре­рывания и по других причинам), тестирует заодно батарейное питание микросхемы, а затем посылает в оба контроллера прерываний команды конца прерываний и завершается командой iret. Однако по ходу своего выполнения обработчик прерывания 70U выполняет команду int 4Ah, которая передает управление на обработчик этого прерывания, тоже вхо­дящий в состав BIOS. Системный обработчик прерывания 4Ali ничего особенно полезного не делает, в сущности представляя собой просто про­грамму-заглушку. Однако программист имеет возможность записать в век­тор 4Ali адрес прикладного обработчика прерываний, который будет ак­тивизироваться прерыванием будильника. Функции прикладного обработ­чика определяет программист.

В примере 3-9 устанавливается прикладной обработчик прерывания 4AU, который сам по себе вызваться никогда не будет, так как по умолча­нию будильник часов реального не работает. Если, однако, прочитать си-

Команды и алгоритмы 141

схемное время с помощью функции 02U прерывания 1АИ, прибавить к нем>' некоторую величину, например, 1 секунду, и установить будильник на это время {с помощью функции 06h прерывания lAli), то через одну секунду будет активизирован наш обработчик. В примере 3-9 этот процесс сделан бесконечным: в обработчике прерываний будильника снова вы­полняется чтение времени,'прибавление к нему 1 секунды и установка будильника на новое время. В результате наш обработчик будет вызываться каждую секунду до завершения всей программы.

Помимо служебной функции установки будильника на следующую секунду, обработчик прерываний выполняет и полезную работу: он выво­дит текущее время в определенное место экрана. Поскольку обработчик активизируется каждую секунду, выводимое значение времени будет об­новляться каждую секунду.

Как уже говорилось, в часах реального времени значение времени хранится в упакованных двоично-десятичных чисел. При выполнении ариф­метических операций с числами BCD (а нашем случае операции заключа­ются в прибаштении 1) необходимо использовать предназначенные для этого команды процессора. В примере проиллюстрировано использование одной из этих команд, конкретно, команды daa.

Для того, чтобы вывести на экран значение времени, его надо преоб­разовать в последовательность кодов ASCII. Процедура преобразования упакованных двоично-десятичных чисел в строку символов также вклю-в рассматриваемый пример. .

;Пример 3-9. Чтение и обработка показаний часов

;реального времени

.586 ;Будут использоваться дополнительные команды

assume CS:code,DS:data

code segment use!6

main proc

mov AX.data ;Настроим DS наш

mov DS,AX ;сегмент данных

;Сохраним исходный вектор 4Ah

mov AX,354Ah

int 2 In

mov word ptr old_4a,BX

mov word ptr old_4a+2,ES ;Установим наш обработчик прерывания 4Ah

mov AX,254Ah

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

push CS ;Настроим DS на сегмент

pop DS ;команд

mov DX,offset new_4a;DS:DX->new_4a

int 21h

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

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

142