Normal quotes
This commit is contained in:
parent
5e10794a24
commit
18011c595a
352 changed files with 6040 additions and 6040 deletions
86
03-07.md
86
03-07.md
|
|
@ -11,7 +11,7 @@ that occur during the timing interval, most notably keyboard and mouse
|
|||
interrupts, will increase the measured time.
|
||||
|
||||
The long-period Zen timer has some of the same effects on the system
|
||||
time as does the precision Zen timer, so it’s a good idea to reboot the
|
||||
time as does the precision Zen timer, so it's a good idea to reboot the
|
||||
system after a session with the long-period Zen timer. The long-period
|
||||
Zen timer does not, however, have the same potential for introducing
|
||||
major inaccuracy into the system clock time during a single timing run
|
||||
|
|
@ -20,7 +20,7 @@ to update normally.
|
|||
|
||||
#### Stopping the Clock {#Heading13}
|
||||
|
||||
There’s a potential problem with the long-period Zen timer. The problem
|
||||
There's a potential problem with the long-period Zen timer. The problem
|
||||
is this: In order to measure times longer than 54 ms, we must maintain
|
||||
not one but two timing components, the timer 0 count and the BIOS
|
||||
time-of-day count. The time-of-day count measures the passage of 54.9 ms
|
||||
|
|
@ -36,9 +36,9 @@ direction.)
|
|||
|
||||
The only way to avoid this problem is to stop timer 0, read both the
|
||||
timer and time-of-day counts while the timer is stopped, and then
|
||||
restart the timer. Alas, the gate input to timer 0 isn’t
|
||||
program-controllable in the PC, so there’s no documented way to stop the
|
||||
timer. (The latched read feature we used in Listing 3.1 doesn’t stop the
|
||||
restart the timer. Alas, the gate input to timer 0 isn't
|
||||
program-controllable in the PC, so there's no documented way to stop the
|
||||
timer. (The latched read feature we used in Listing 3.1 doesn't stop the
|
||||
timer; it latches a count, but the timer keeps running.) What should we
|
||||
do?
|
||||
|
||||
|
|
@ -49,23 +49,23 @@ until the count is loaded. Surprisingly, the timer count remains
|
|||
readable and correct while the timer is waiting for the initial load.
|
||||
|
||||
In my experience, this approach works beautifully with fully
|
||||
8253-compatible chips. However, there’s no guarantee that it will always
|
||||
work, since it programs the 8253 in an undocumented way. What’s more,
|
||||
8253-compatible chips. However, there's no guarantee that it will always
|
||||
work, since it programs the 8253 in an undocumented way. What's more,
|
||||
IBM chose not to implement compatibility with this particular 8253
|
||||
feature in the custom chips used in PS/2 computers. On PS/2 computers,
|
||||
we have no choice but to latch the timer 0 count and then stop the BIOS
|
||||
count (by disabling interrupts) as quickly as possible. We’ll just have
|
||||
count (by disabling interrupts) as quickly as possible. We'll just have
|
||||
to accept the fact that on PS/2 computers we may occasionally get a
|
||||
reading that’s off by 54 ms, and leave it at that.
|
||||
reading that's off by 54 ms, and leave it at that.
|
||||
|
||||
I’ve set up Listing 3.5 so that it can assemble to either use or not use
|
||||
I've set up Listing 3.5 so that it can assemble to either use or not use
|
||||
the undocumented timer-stopping feature, as you please. The **PS2**
|
||||
equate selects between the two modes of operation. If **PS2** is 1 (as
|
||||
it is in Listing 3.5), then the latch-and-read method is used; if
|
||||
**PS2** is 0, then the undocumented timer-stop approach is used. The
|
||||
latch-and-read method will work on all PC-compatible computers, but may
|
||||
occasionally produce results that are incorrect by 54 ms. The timer-stop
|
||||
approach avoids synchronization problems, but doesn’t work on all
|
||||
approach avoids synchronization problems, but doesn't work on all
|
||||
computers.
|
||||
|
||||
**LISTING 3.5 LZTIMER.ASM**
|
||||
|
|
@ -103,13 +103,13 @@ computers.
|
|||
; more than adequate.
|
||||
;
|
||||
; Note: The PS/2 version is assembled by setting the symbol PS2 to 1.
|
||||
; PS2 must be set to 1 on PS/2 computers because the PS/2’s
|
||||
; PS2 must be set to 1 on PS/2 computers because the PS/2's
|
||||
; timers are not compatible with an undocumented timer-stopping
|
||||
; feature of the 8253; the alternative timing approach that
|
||||
; must be used on PS/2 computers leaves a short window
|
||||
; during which the timer 0 count and the BIOS timer count may
|
||||
; not be synchronized. You should also set the PS2 symbol to
|
||||
; 1 if you’re getting erratic or obviously incorrect results.
|
||||
; 1 if you're getting erratic or obviously incorrect results.
|
||||
;
|
||||
; Note: When PS2 is 0, the code relies on an undocumented 8253
|
||||
; feature to get more reliable readings. It is possible that
|
||||
|
|
@ -140,7 +140,7 @@ computers.
|
|||
;
|
||||
; Note: These routines can introduce inaccuracies of up to a few
|
||||
; tenths of a second into the system clock count for each
|
||||
; code section timed. Consequently, it’s a good idea to
|
||||
; code section timed. Consequently, it's a good idea to
|
||||
; reboot at the conclusion of timing sessions. (The
|
||||
; battery-backed clock, if any, is not affected by the Zen
|
||||
; timer.)
|
||||
|
|
@ -148,7 +148,7 @@ computers.
|
|||
; All registers and all flags are preserved by all routines.
|
||||
;
|
||||
|
||||
Code segment word public ‘CODE’
|
||||
Code segment word public ‘CODE'
|
||||
assume cs: Code, ds:nothing
|
||||
public ZTimerOn, ZTimerOff, ZTimerReport
|
||||
|
||||
|
|
@ -157,7 +157,7 @@ computers.
|
|||
; system; when PS2 is 0, the readings are more reliable if the
|
||||
; computer supports the undocumented timer-stopping feature,
|
||||
; but may be badly off if that feature is not supported. In
|
||||
; fact, timer-stopping may interfere with your computer’s
|
||||
; fact, timer-stopping may interfere with your computer's
|
||||
; overall operation by putting the 8253 into an undefined or
|
||||
; incorrect state. Use with caution!!!
|
||||
;
|
||||
|
|
@ -231,10 +231,10 @@ computers.
|
|||
OutputStr labelbyte
|
||||
db 0dh, 0ah, ‘Timed count: ‘
|
||||
TimedCountStr db10 dup (?)
|
||||
db’ microseconds’, 0dh, 0ah
|
||||
db ‘$’
|
||||
db' microseconds', 0dh, 0ah
|
||||
db ‘$'
|
||||
;
|
||||
; Temporary storage for timed count as it’s divided down by powers
|
||||
; Temporary storage for timed count as it's divided down by powers
|
||||
; of ten when converting from doubleword binary to ASCII.
|
||||
;
|
||||
CurrentCountLow dw ?
|
||||
|
|
@ -262,25 +262,25 @@ computers.
|
|||
;
|
||||
TurnOverStrlabelbyte
|
||||
db 0dh, 0ah
|
||||
db ‘****************************************************’
|
||||
db ‘****************************************************'
|
||||
db 0dh, 0ah
|
||||
db’* Either midnight passed or an hour or more passed *’
|
||||
db'* Either midnight passed or an hour or more passed *'
|
||||
db 0dh, 0ah
|
||||
db’* while timing was in progress. If the former was *’
|
||||
db'* while timing was in progress. If the former was *'
|
||||
db 0dh, 0ah
|
||||
db’* the case, please rerun the test; if the latter *’
|
||||
db'* the case, please rerun the test; if the latter *'
|
||||
db 0dh, 0ah
|
||||
db’* was the case, the test code takes too long to *’
|
||||
db'* was the case, the test code takes too long to *'
|
||||
db 0dh, 0ah
|
||||
db’* run to be timed by the long-period Zen timer. *’
|
||||
db'* run to be timed by the long-period Zen timer. *'
|
||||
db 0dh, 0ah
|
||||
db ‘* Suggestions: use the DOS TIME command, the DOS *’
|
||||
db ‘* Suggestions: use the DOS TIME command, the DOS *'
|
||||
db 0dh, 0ah
|
||||
db ‘* time function, or a watch. *’
|
||||
db ‘* time function, or a watch. *'
|
||||
db 0dh, 0ah
|
||||
db ‘****************************************************’
|
||||
db ‘****************************************************'
|
||||
db 0dh, 0ah
|
||||
db’$’
|
||||
db'$'
|
||||
|
||||
;********************************************************************
|
||||
;* Routine called to start timing. *
|
||||
|
|
@ -302,7 +302,7 @@ computers.
|
|||
mov al,00110100b ;mode 2
|
||||
out MODE_8253,al
|
||||
;
|
||||
; Set the timer count to 0, so we know we won’t get another
|
||||
; Set the timer count to 0, so we know we won't get another
|
||||
; timer interrupt right away.
|
||||
; Note: this introduces an inaccuracy of up to 54 ms in the system
|
||||
; clock count each time it is executed.
|
||||
|
|
@ -329,7 +329,7 @@ computers.
|
|||
;
|
||||
; Store the timing start BIOS count.
|
||||
; (Since the timer count was just set to 0, the BIOS count will
|
||||
; stay the same for the next 54 ms, so we don’t need to disable
|
||||
; stay the same for the next 54 ms, so we don't need to disable
|
||||
; interrupts in order to avoid getting a half-changed count.)
|
||||
;
|
||||
push ds
|
||||
|
|
@ -394,12 +394,12 @@ computers.
|
|||
;
|
||||
; This is where a one-instruction-long window exists on the PS/2.
|
||||
; The timer count and the BIOS count can lose synchronization;
|
||||
; since the timer keeps counting after it’s latched, it can turn
|
||||
; over right after it’s latched and cause the BIOS count to turn
|
||||
; since the timer keeps counting after it's latched, it can turn
|
||||
; over right after it's latched and cause the BIOS count to turn
|
||||
; over before interrupts are disabled, leaving us with the timer
|
||||
; count from before the timer turned over coupled with the BIOS
|
||||
; count from after the timer turned over. The result is a count
|
||||
; that’s 54 ms too long.
|
||||
; that's 54 ms too long.
|
||||
;
|
||||
|
||||
else
|
||||
|
|
@ -420,7 +420,7 @@ computers.
|
|||
cli ;stop the BIOS count
|
||||
;
|
||||
; Read the BIOS count. (Since interrupts are disabled, the BIOS
|
||||
; count won’t change.)
|
||||
; count won't change.)
|
||||
;
|
||||
push ds
|
||||
sub ax,ax
|
||||
|
|
@ -526,9 +526,9 @@ computers.
|
|||
|
||||
;
|
||||
; Called by ZTimerOff to stop the timer and add the result to
|
||||
; ReferenceCount for overhead measurements. Doesn’t need to look
|
||||
; ReferenceCount for overhead measurements. Doesn't need to look
|
||||
; at the BIOS count because timing a zero-length code fragment
|
||||
; isn’t going to take anywhere near 54 ms.
|
||||
; isn't going to take anywhere near 54 ms.
|
||||
;
|
||||
|
||||
ReferenceZTimerOff procnear
|
||||
|
|
@ -596,8 +596,8 @@ computers.
|
|||
;
|
||||
mov ax,[StartBIOSCountHigh]
|
||||
cmp ax,[EndBIOSCountHigh]
|
||||
jz CalcBIOSTime ;hour count didn’t change,
|
||||
; so everything’s fine
|
||||
jz CalcBIOSTime ;hour count didn't change,
|
||||
; so everything's fine
|
||||
inc ax
|
||||
cmp ax,[EndBIOSCountHigh]
|
||||
jnz TestTooLong ;midnight or two hour
|
||||
|
|
@ -606,14 +606,14 @@ computers.
|
|||
mov ax,[EndBIOSCountLow]
|
||||
cmp ax,[StartBIOSCountLow]
|
||||
jb CalcBIOSTime ;a single hour boundary
|
||||
; passed--that’s OK, so long as
|
||||
; the total time wasn’t more
|
||||
; passed--that's OK, so long as
|
||||
; the total time wasn't more
|
||||
; than an hour
|
||||
|
||||
;
|
||||
; Over an hour elapsed or midnight passed during timing, which
|
||||
; renders the results invalid. Notify the user. This misses the
|
||||
; case where a multiple of 24 hours has passed, but we’ll rely
|
||||
; case where a multiple of 24 hours has passed, but we'll rely
|
||||
; on the perspicacity of the user to detect that case.
|
||||
;
|
||||
TestTooLong:
|
||||
|
|
@ -665,7 +665,7 @@ computers.
|
|||
mov di,offset PowersOfTenEnd - offset PowersOfTen - 4
|
||||
mov si,offset TimedCountStr
|
||||
CTSNextDigit:
|
||||
mov bl,’0’
|
||||
mov bl,'0'
|
||||
CTSLoop:
|
||||
mov ax,[CurrentCountLow]
|
||||
mov dx,[CurrentCountHigh]
|
||||
|
|
|
|||
Loading…
Reference in a new issue