Using the 8254 Timer-Counter. Understanding the role of the system’s 8254 programmable Interval-Timer/Counter. Displaying ‘Time-Of-Day’. Algorithm steps: Get the count of timer-interrupts so far today Convert these ‘timer-ticks’ into seconds
Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.
Using the 8254 Timer-Counter
Understanding the role of the system’s 8254 programmable Interval-Timer/Counter
main memory
Number of timer-tick
interrupts so far today
(longword at 0x0046C)
0x00500
ROM-BIOS DATA AREA
0040:006C
tick_count
0x00400
Interrupt Vector Table
(for real-mode)
0x00000
xor%ax, %ax# address segment zero
mov%ax, %fs# using FS register
mov%fs:0x046C, %eax# copy tick-count to EAX
mov%eax, total_ticks# save in a local variable
segment-override prefix (segment used would be %ds)
total_ticks_today
total_seconds_today =
number of ticks-per-second
The number of ‘ticks-per-second’ is based upon the way
the PC’s timing hardware has been programmed
8284
PCLK
1193182 Hz
Channel 0
CLK0
OUT0
Interrupt IRQ0
GATE0
Port 0x61, bit #4
CLK1
Channel 1
OUT1
DRAM refresh
GATE1
Port 0x61, bit #5
CLK2
Channel 2
OUT2
GATE2
speaker
AND
Port 0x61, bit #0
8254 PIT
+5 V
Port 0x61, bit #1
COUNT REGISTER
CLK
MSB
LSB
OUT
MSB
LSB
LATCH REGISTER
GATE
STATUS
TIMER/COUNTER CHANNEL
7 6 5 4 3 2 1 0
CHANNEL
COMMAND
OUTPUT MODE
binary
/ BCD
Output Mode
000 = one-shot level
001 = retriggerable
010 = rate-generator
011 = square-wave
100 = software strobe
101 = hardware strobe
Counting Mode
0 = binary
1 = BCD
Channel-ID
00 = chn 0
01 = chn 1
10 = chn 2
Command-ID
00 = Latch
01 = LSB r/w
10 = MSB r/w
11 = LSB-MSB r/w
Commands are sent to the 8254 via io/port 0x43
output-frequency = input-frequency / frequency-divisor
= 1193182 / 65536 (approximately 18.2)
total_seconds = total_ticks / ticks_per_second
= total_ticks / (1193182 / 65536)
= ( total_ticks * 65536 ) / 1193183
Before executing the MUL instruction…
EAX
multiplicand (32-bits)
reg (or mem)
multiplier (32-bits)
32-bit operands
mull reg_or_mem
Here’s the instruction…
After executing the MUL instruction…
product (64-bits)
EDX
EAX
64-bit product
Before executing the DIV instruction…
dividend (64-bits)
EDX
EAX
64-bit dividend
reg (or mem)
divisor (32-bits)
32-bit operand
divl reg_or_mem
Here’s the instruction…
After executing the DIV instruction…
two results (32-bits)
EDX
EAX
32-bit remainder
32-bit quotient
# total_seconds = ( total_ticks * FREQ_DIVISOR ) / PULSES_PER_SEC
movtotal_ticks, %eax
mov$FREQ_DIVISOR, %ecx
mul%ecx
mov$PULSES_PER_SEC, %ecx
div%ecx
mov%eax, total_seconds
# Now integer-quotient is in EAX, and integer-remainder is in EDX
HH:MM:SS am/pm
hours
seconds
morning or
afternoon
minutes
So we need to compute four numerical values from the ‘total_seconds’ integer
We use these arithmetical ideas:
# Recall: quotient was in EAX, remainder was in EDX, divisor was in ECX
add%edx, %edx# doubles the remainder
sub%ecx, %edx# computes: 2*quotient – divisor
# now carry-flag is clear in case 2*quotient >= divisor
cmc# complement the carry-flag bit
# now carry-flag is set in case 2*quotient >= divisor
adc$0, %eax# add the carry-flag to the quotient
# So this achieves the same effect as the ‘rounding rule’, but wit no jump!