Normal quotes

This commit is contained in:
James Gregory 2013-12-30 18:34:31 +11:00
commit 18011c595a
352 changed files with 6040 additions and 6040 deletions

View file

@ -2,7 +2,7 @@
[Previous](04-02.html) [Table of Contents](index.html) [Next](04-04.html)
------------------------ --------------------------------- --------------------
Back to the 8-bit bus cycle-eater. As I’ve said, in 8088 work you should
Back to the 8-bit bus cycle-eater. As I've said, in 8088 work you should
strive to use byte-sized memory variables whenever possible. That does
*not* mean that you should use 2 byte-sized memory accesses to
manipulate a word-sized memory variable in preference to 1 word-sized
@ -18,16 +18,16 @@ versus:
Recall that every access to a memory byte takes at least 4 cycles; that
limitation is built right into the 8088. The 8088 is also built so that
the second byte-sized memory access to a 16-bit memory variable takes
just those 4 cycles and no more. There’s no way you can manipulate the
just those 4 cycles and no more. There's no way you can manipulate the
second byte of a word-sized memory variable faster with a second
separate byte-sized instruction in less than 4 cycles. As a matter of
fact, you’re bound to access that second byte much more slowly with a
fact, you're bound to access that second byte much more slowly with a
separate instruction, thanks to the overhead of instruction fetching and
execution, address calculation, and the like.
For example, consider Listing 4.3, which performs 1,000 word-sized reads
from memory. This code runs in 3.77 µs per word read on a 4.77 MHz 8088.
That’s 45 percent faster than the 5.49 µs per word read of Listing 4.4,
That's 45 percent faster than the 5.49 µs per word read of Listing 4.4,
which reads the same 1,000 words as Listing 4.3 but does so with 2,000
byte-sized reads. Both listings perform exactly the same number of
memory accesses—2,000 accesses, each byte-sized, as all 8088 memory
@ -67,14 +67,14 @@ efficient at that task than your code can possibly be.
Word-sized variables should be stored in registers to the greatest
feasible extent, since registers are inside the 8088, where 16-bit
operations are just as fast as 8-bit operations because the 8-bit
cycle-eater can’t get at them. In fact, it’s a good idea to keep as many
cycle-eater can't get at them. In fact, it's a good idea to keep as many
variables of all sorts in registers as you can. Instructions with
register-only operands execute very rapidly, partially because they
avoid both the time-consuming memory accesses and the lengthy address
calculations associated with memory operands.
There is yet another reason why register operands are preferable to
memory operands, and it’s an unexpected effect of the 8-bit bus
memory operands, and it's an unexpected effect of the 8-bit bus
cycle-eater. Instructions with only register operands tend to be shorter
(in terms of bytes) than instructions with memory operands, and when it
comes to performance, shorter is usually better. In order to explain why
@ -82,32 +82,32 @@ that is true and how it relates to the 8-bit bus cycle-eater, I must
diverge for a moment.
For the last few pages, you may well have been thinking that the 8-bit
bus cycle-eater, while a nuisance, doesn’t seem particularly subtle or
bus cycle-eater, while a nuisance, doesn't seem particularly subtle or
difficult to quantify. After all, any instruction reference tells us
exactly how many cycles each instruction loses to the 8-bit bus
cycle-eater, doesn’t it?
cycle-eater, doesn't it?
Yes and no. It’s true that in general we know approximately how much
Yes and no. It's true that in general we know approximately how much
longer a given instruction will take to execute with a word-sized memory
operand than with a byte-sized operand, although the dynamic RAM refresh
and wait state cycle-eaters (which I’ll cover a little later) can raise
and wait state cycle-eaters (which I'll cover a little later) can raise
the cost of the 8-bit bus cycle-eater considerably. However, *all*
word-sized memory accesses lose 4 cycles to the 8-bit bus cycle-eater,
and there’s one sort of word-sized memory access we haven’t discussed
and there's one sort of word-sized memory access we haven't discussed
yet: instruction fetching. The ugliest manifestation of the 8-bit bus
cycle-eater is in fact the prefetch queue cycle-eater.
### The Prefetch Queue Cycle-Eater {#Heading9}
In an 8088 context, here’s the prefetch queue cycle-eater in a nutshell:
The 8088’s 8-bit external data bus keeps the Bus Interface Unit from
In an 8088 context, here's the prefetch queue cycle-eater in a nutshell:
The 8088's 8-bit external data bus keeps the Bus Interface Unit from
fetching instruction bytes as fast as the 16-bit Execution Unit can
execute them, so the Execution Unit often lies idle while waiting for
the next instruction byte to be fetched.
Exactly why does this happen? Recall that the 8088 is an 8086
internally, but accesses word-sized memory data at only one-half the
maximum rate of the 8086 due to the 8088’s 8-bit external data bus.
maximum rate of the 8086 due to the 8088's 8-bit external data bus.
Unfortunately, instructions are among the word-sized data the 8086
fetches, meaning that the 8088 can fetch instructions at only one-half
the speed of the 8086. On the other hand, the 8086-equivalent Execution
@ -119,24 +119,24 @@ up idling while waiting for instructions bytes to arrive.
The BIU can fetch instruction bytes at a maximum rate of one byte every
4 cycles—*and that 4-cycle per instruction byte rate is the ultimate
limit on overall instruction execution time, regardless of EU speed.*
While the EU may execute a given instruction that’s already in the
prefetch queue in less than 4 cycles per byte, over time the EU can’t
execute instructions any faster than they can arrive—and they can’t
While the EU may execute a given instruction that's already in the
prefetch queue in less than 4 cycles per byte, over time the EU can't
execute instructions any faster than they can arrive—and they can't
arrive faster than 1 byte every 4 cycles.
Clearly, then, the prefetch queue cycle-eater is nothing more than one
aspect of the 8-bit bus cycle-eater. 8088 code often runs at less than
the Execution Unit’s maximum speed because the 8-bit data bus can’t keep
up with the demand for instruction bytes. That’s straightforward
the Execution Unit's maximum speed because the 8-bit data bus can't keep
up with the demand for instruction bytes. That's straightforward
enough—so why all the fuss about the prefetch queue cycle-eater?
What makes the prefetch queue cycle-eater tricky is that it’s
What makes the prefetch queue cycle-eater tricky is that it's
undocumented and unpredictable. That is, with a word-sized memory
access, such as
mov [bx],ax
it’s well-documented that an extra 4 cycles will always be required to
it's well-documented that an extra 4 cycles will always be required to
write the upper byte of AX to memory. Not so with the prefetch queue
cycle-eater lurking nearby. For instance, the instructions
@ -147,17 +147,17 @@ cycle-eater lurking nearby. For instance, the instructions
shr ax,1
should execute in 10 cycles, since each **SHR** takes 2 cycles to
execute, according to Intel’s specifications. Those specifications
contain Intel’s official instruction execution times, but in this
execute, according to Intel's specifications. Those specifications
contain Intel's official instruction execution times, but in this
case—and in many others—the specifications are drastically wrong. Why?
Because they describe execution time *once an instruction reaches the
prefetch queue.* They say nothing about whether a given instruction will
be in the prefetch queue when it’s time for that instruction to run, or
be in the prefetch queue when it's time for that instruction to run, or
how long it will take that instruction to reach the prefetch queue if
it’s not there already. Thanks to the low performance of the 8088’s
external data bus, that’s a glaring omission—but, alas, an unavoidable
one. Let’s look at why the official execution times are wrong, and why
that can’t be helped.
it's not there already. Thanks to the low performance of the 8088's
external data bus, that's a glaring omission—but, alas, an unavoidable
one. Let's look at why the official execution times are wrong, and why
that can't be helped.
------------------------ --------------------------------- --------------------
[Previous](04-02.html) [Table of Contents](index.html) [Next](04-04.html)