Initial conversion to markdown
This commit is contained in:
parent
a96a114403
commit
5e10794a24
362 changed files with 67353 additions and 0 deletions
111
11-07.md
Normal file
111
11-07.md
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](11-06.html) [Table of Contents](index.html) [Next](11-08.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**LISTING 11.5 L11-5.ASM**
|
||||
|
||||
;
|
||||
; *** Listing 11.5 ***
|
||||
;
|
||||
; Measures the performance of adding an immediate value
|
||||
; to a memory variable, for comparison with Listing 11.4,
|
||||
; which adds an immediate value to a register.
|
||||
;
|
||||
jmp Skip
|
||||
;
|
||||
even ;always make sure word-sized memory
|
||||
; variables are word-aligned!
|
||||
WordVar dw 0
|
||||
;
|
||||
Skip:
|
||||
call ZTimerOn
|
||||
rept 1000
|
||||
add [WordVar]100h
|
||||
endm
|
||||
call ZTimerOff
|
||||
|
||||
What’s going on? Simply this: Instruction fetching is controlling
|
||||
overall execution time on *both* processors. Both the 8088 in a PC and
|
||||
the 286 in an AT can execute the bytes of the instructions in Listings
|
||||
11.4 and 11.5 faster than they can be fetched. Since the instructions
|
||||
are exactly the same lengths on both processors, it stands to reason
|
||||
that the ratio of the overall execution times of the instructions should
|
||||
be the same on both processors as well. Instruction length controls
|
||||
execution time, and the instruction lengths are the same—therefore the
|
||||
ratios of the execution times are the same. The 286 can both fetch and
|
||||
execute instruction bytes faster than the 8088 can, so code executes
|
||||
much faster on the 286; nonetheless, because the 286 can also execute
|
||||
those instruction bytes much faster than it can fetch them, overall
|
||||
performance is still largely determined by the size of the instructions.
|
||||
|
||||
Is this always the case? No. When the prefetch queue is full,
|
||||
memory-accessing instructions on the 286 and 386 are much faster
|
||||
(relative to register-only instructions) than they are on the 8088.
|
||||
Given the system wait states prevalent on 286 and 386 computers,
|
||||
however, the prefetch queue is likely to be empty quite a bit,
|
||||
especially when code consisting of instructions with short EU execution
|
||||
times is executed. Of course, that’s just the sort of code we’re likely
|
||||
to write when we’re optimizing, so the performance of high-speed code is
|
||||
more likely to be controlled by instruction size than by EU execution
|
||||
time on most 286 and 386 computers, just as it is on the PC.
|
||||
|
||||
All of which is just a way of saying that faster memory access and EA
|
||||
calculation notwithstanding, it’s just as desirable to keep instructions
|
||||
short and memory accesses to a minimum on the 286 and 386 as it is on
|
||||
the 8088. And the way to do that is to use the registers as heavily as
|
||||
possible, use string instructions, use short forms of instructions, and
|
||||
the like.
|
||||
|
||||
The more things change, the more they remain the same....
|
||||
|
||||
#### POPF and the 286 {#Heading17}
|
||||
|
||||
We’ve one final 286-related item to discuss: the hardware malfunction of
|
||||
**POPF** under certain circumstances on the 286.
|
||||
|
||||
The problem is this: Sometimes **POPF** permits interrupts to occur when
|
||||
interrupts are initially off and the setting popped into the Interrupt
|
||||
flag from the stack keeps interrupts off. In other words, an interrupt
|
||||
can happen even though the Interrupt flag is never set to 1. Now, I
|
||||
don’t want to blow this particular bug out of proportion. It only causes
|
||||
problems in code that cannot tolerate interrupts under any
|
||||
circumstances, and that’s a rare sort of code, especially in user
|
||||
programs. However, some code really does need to have interrupts
|
||||
absolutely disabled, with no chance of an interrupt sneaking through.
|
||||
For example, a critical portion of a disk BIOS might need to retrieve
|
||||
data from the disk controller the instant it becomes available; even a
|
||||
few hundred microseconds of delay could result in a sector’s worth of
|
||||
data misread. In this case, one misplaced interrupt during a **POPF**
|
||||
could result in a trashed hard disk if that interrupt occurs while the
|
||||
disk BIOS is reading a sector of the File Allocation Table.
|
||||
|
||||
There is a workaround for the **POPF** bug. While the workaround is easy
|
||||
to use, it’s considerably slower than **POPF**, and costs a few bytes as
|
||||
well, so you won’t want to use it in code that can tolerate interrupts.
|
||||
On the other hand, in code that truly cannot be interrupted, you should
|
||||
view those extra cycles and bytes as cheap insurance against mysterious
|
||||
and erratic program crashes.
|
||||
|
||||
One obvious reason to discuss the **POPF** workaround is that it’s
|
||||
useful. Another reason is that the workaround is an excellent example of
|
||||
Zen-level assembly coding, in that there’s a well-defined goal to be
|
||||
achieved but no obvious way to do so. The goal is to reproduce the
|
||||
functionality of the **POPF** instruction without using **POPF**, and
|
||||
the place to start is by asking exactly what **POPF** does.
|
||||
|
||||
All **POPF** does is pop the word on top of the stack into the FLAGS
|
||||
register, as shown in Figure 11.4. How can we do that without **POPF**?
|
||||
Of course, the 286’s designers intended us to use **POPF** for this
|
||||
purpose, and didn’t intentionally provide any alternative approach, so
|
||||
we’ll have to devise an alternative approach of our own. To do that,
|
||||
we’ll have to search for instructions that contain some of the same
|
||||
functionality as **POPF**, in the hope that one of those instructions
|
||||
can be used in some way to replace **POPF**.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](11-06.html) [Table of Contents](index.html) [Next](11-08.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
Loading…
Reference in a new issue