
Системний таймер
Мета роботи: навчитися використовувати переривання системного таймера й годинника реального часу RTC, одержати навички в обробці чисел у форматі BCD для їхнього виводу на екран.
-
Теоретичні відомості
Як відомо, будь-який сучасний персональний комп'ютер містить такі пристрої керування процесами як годинник реального часу RTC (Real time clock) і системний таймер. Годинник RTC зазвичай міститься на материнській платі і живиться від акумулятора, що робить цей пристрій енергонезалежним стосовно ПК і дозволяє йому працювати навіть у тому випадку, коли комп'ютер перебуває у виключеному стані. Годинник реального часу в основному використовується для визначення поточної дати й часу, а також для установки будильника. Системний таймер використовується для генерації необхідних затримок, що необхідно при роботі з динаміками (генерація імпульсів), портами (забезпечення необхідної швидкості передачі) і багатьма іншими програмами.
Робота з годинником реального часу rtc і системним таймером
Уся інформація про годинник RTC знаходиться в CMOS – Пам’яті комп’ютера. Для того, щоб одержати необхідну інформацію не звертаючись до даної пам'яті напряму, серед переривань BIOS існує переривання введення-виводу часу INT 1Ah. Дане переривання дозволяє виконувати читання/запис часу й дати з годинника RTC, а також працювати з лічильником часу й годинником системного таймера. Для формування затримок за допомогою системного таймера використовується 86h функція 15h переривання. У таблиці 1 наведений список основних функцій, необхідних для виконання даної лабораторної роботи.
Таблиця 1
Переривання INT 1Ah |
АН = 04h — Визначити дату RTC
= день (у формі BCD)
|
||||
АН = 02h — Визначити час RTC
немає
|
|||||
Переривання INT 15h |
АН = 86h — Формування затримки
тий
|
Bcd форма запису чисел
BCD (binary-coded decimal, packed), або ж ДДК (двійково-десятковий код) – форма запису чисел, у якому кожний розряд десяткового числа записаний у вигляді його 4-бітного двійкового коду. Наприклад, число 220 у вигляді бінарного коду представляється як 1101 1100, а в ДДК – 0010 0010 0000.
Нехай у старший розряд регістру CX записане двоцифрове число 32 у вигляді ДДК (CH=00110010b). Для будь-якого використання даного числа (наприклад, виводу його на екран), необхідно виділити з нього кожну цифру окремо. Перша цифра вибирається шляхом логічного зсуву вправо на 4 розряди із заповненням розрядів ліворуч нулями. У результаті даної операції в CH буде міститись число 3:
00110010 |
4-> |
00000011 |
Необхідно відзначити, що перед зсувом зміст CH необхідно зберегти будь-яким способом (наприклад, записати в стек), інакше отримання другої цифри числа буде неможливим. Після зсуву необхідно якось обробити отриману цифру, після чого відновити колишнє значення CH для одержання наступної цифри числа. Для одержання в CH першої цифри числа 32 найпростіший шлях - це накласти на число перетворюючу бітову маску 00001111 та виконати операцію AND CH, 11110000b, у результаті чого отримаємо:
AND |
00110010 |
00001111 |
|
= |
00000010 |
Тобто в CH буде зберігається цифра 2. У форматі команд асемблера дане перетворення буде виглядати так:
MOV CH,00110010b MOV AL,CH SHR AL,4 ;AL=00000011b MOV AL,CH AND AL,00001111b ;AL=00000010b |
Лістинг програми «Плинний рядок» («Бегущая строка»)
.286 ASSUME CS:CODE,DS:DATA,SS:STK
STK SEGMENT STACK STKD DW 64 DUP(?) STK ENDS
CODE SEGMENT _beg: MOV AX,DATA MOV DS,AX MOV AX,0003h ;init text mode INT 10h ;80x25
_lop: MOV AH,02h ;get system time from RTC INT 1Ah ;Ch-hours, Cl-minutes Dl-seconds
CALL outbcdnumb ;**OUTPUT OF HOURS** MOV SI,SWITCH ;output of the separator ADD X,5 CALL outdigit
MOV CH,CL ;**OUTPUT OF MINUTES** CALL outbcdnumb MOV SI,SWITCH ;output of the separator ADD X,5 CALL outdigit
MOV CH,DH ;**OUTPUT OF SECONDS** CALL outbcdnumb
MOV AH,02h ;Setting cursor position MOV DH,25 ;to the end of the screen. MOV BH,00h ;It will be unvisible INT 10h
MOV AH,86h ;DELAY FOR 1 SEC MOV DX,0A120h ;DX:CX = 0007A120h MOV CX,0007h ;in microseconds INT 15h
MOV AL,X ;LEFT SHIFT OF X SUB AL,41 ; ON THE SCREEN JZ _nul JMP _nex _nul: MOV AX,0003h ;if X==0 then move X INT 10h ;to the end of the screen MOV AL,30 ;and clear screen _nex: MOV X,AL
XOR SWITCH,1 ;switching between 10 and 11 ;codes of separate symbol
MOV AH,01h ;reading the state of the INT 16h ;pressed key in queque jnz _ext ;if pressed then exit
JMP _lop
_ext: .EXIT
;PROCEDURE outdigit ; SI : CHAR NUMBER OF DIGIT TO OUT ; X,Y : COORDINATES ;OUTPUT THE DIGIT WITH A NUMBER SI AND ;COORDINATES X AND Y outdigit PROC NEAR PUSHA
MOV AX,SI ; CALCULATES THE OFFSET MOV BX,25 ; AFTER THE BEGIN OF MUL BX ; OUTPUT TABLE. MOV SI,AX ;CHAR OFFSET MOV DH,Y ;ROW TO OUT MOV DL,0 ;COL TO OUT
MOV CX,25 _out: PUSH CX
PUSH DX ADD DL,X MOV AH,02h ;SET CURSOR MOV BH,00h ;VIDEO PAGE INT 10h
MOV AH,09h ;OUT CHAR AT CURSOR
MOV AL,zer+SI ;CHAR MOV CX,01h ;COUNT MOV BL,02h ;TEXT ATTRIBUTE(COLOR) ADD BL,80h ;FLASHING COLOR INT 10h
INC SI POP DX INC DL CMP DL,5 JE _inc JMP _next
_inc: INC DH ;INCREASE Y POSITION MOV DL,0 ;"RETURN CARET"
_next: POP CX LOOP _out
POPA RET outdigit ENDP
;PROCEDURE outbcdnumb ; CH : NUMBER IN THE BCD FORM ;OUTS THE NUMBER CH AND ;CHANGE FOR IT THE COORDINATE X outbcdnumb PROC NEAR XOR AH,AH ;extracts higher digit MOV AL,CH ;from the hour number SHR AL,4 ;in BCD form
MOV SI,AX ;filling the arguments of procedure outdigit ADD X,5 ;by the symbol to write and its coordinates CALL outdigit ;call out procedure
XOR AH,AH ;extracts lower digit MOV AL,CH ;from the hour number AND AL,00001111b
MOV SI,AX ADD X,5 ;shift of the X coordinate to the next digit CALL outdigit ;out next digit of hour RET outbcdnumb ENDP CODE ENDS
DATA SEGMENT X DB 2 ;X coordinate of the text Y DB 3 ;Y coordinate of the text SWITCH DW 10 zer DB '████ ' DB '█ █ ' DB '█ █ ' DB '█ █ ' DB '████ '
one DB '██ ' DB ' █ ' DB ' █ ' DB ' █ ' DB '███ '
two DB '████ ' DB ' █ ' DB '████ ' DB '█ ' DB '████ '
thr DB '████ ' DB ' █ ' DB '████ ' DB ' █ ' DB '████ '
fou DB '█ █ ' DB '█ █ ' DB '████ ' DB ' █ ' DB ' █ '
fiv DB '████ ' DB '█ ' DB '████ ' DB ' █ ' DB '████ '
six DB '████ ' DB '█ ' DB '████ ' DB '█ █ ' DB '████ '
sev DB '████ ' DB ' █ ' DB ' █ ' DB ' █ ' DB ' █ '
eig DB '████ ' DB '█ █ ' DB '████ ' DB '█ █ ' DB '████ '
nin DB '████ ' DB '█ █ ' DB '████ ' DB ' █ ' DB '████ '
dts DB ' ' DB ' █ ' DB ' ' DB ' █ ' DB ' '
emp DB ' ' DB ' ' DB ' ' DB ' ' DB ' ' DATA ENDS
END _beg |
|
Рис. 1. Результат роботи програми
У наведеному прикладі використана директива .286. Це необхідно для підтримки команд PUSHA і POPA. Дані команди підтримуються процесорами, тільки починаючи з покоління 80286.
Для виводу символів на екран у прикладі були використано 02h і 09h функції переривання відеосервісу INT 10h (див. Таблицю 2).
Таблиця 2
Переривання INT 10h |
АН = 02h — Встановити позицію курсору. Установка на рядок 25 робить курсор невидимим.
|
||
АН = 09h — Вивести символ/атрибут у текстовому режимі (або пік- сель/колір у графічному режимі) в поточній позиції курсору.
|
Для очікування натискання клавіші використовується 01h функція переривання клавіатури 16h (див. Таблицю 3). Вона дозволяє визначити наявність натиснутого символу в буфері клавіатури, його Ascii-Код і скан-код відповідної клавіші.
Таблиця 3
Переривання INT 16h |
АН = 01h — Перевірка стану буфера клавіатури на наявність символів, відповідних до клавіш 84- клавішної клавіатури.
Вивід: ZF =0, буфер порожній ZF =1, у буфері присутній символ AL = Ascii-Код символу натиснутої клавіші АН = скан-код натиснутої клавіші |