Remove navigation and footer from each page
This commit is contained in:
parent
18011c595a
commit
efd73dca38
362 changed files with 80 additions and 4419 deletions
14
01-01.md
14
01-01.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------------- --------------------------------- --------------------
|
||||
[Previous](about_author.html) [Table of Contents](index.html) [Next](01-02.html)
|
||||
------------------------------- --------------------------------- --------------------
|
||||
|
||||
*Part I* {align="center"}
|
||||
--------
|
||||
|
||||
|
|
@ -114,12 +110,4 @@ with just a little thought. As we'll see, handcrafted assembly language
|
|||
and optimizing compilers matter, but less than you might think, in the
|
||||
grand scheme of things—and they scarcely matter at all unless they're
|
||||
used in the context of a good design and a thorough understanding of
|
||||
both the task at hand and the PC.
|
||||
|
||||
------------------------------- --------------------------------- --------------------
|
||||
[Previous](about_author.html) [Table of Contents](index.html) [Next](01-02.html)
|
||||
------------------------------- --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
both the task at hand and the PC.
|
||||
14
01-02.md
14
01-02.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](01-01.html) [Table of Contents](index.html) [Next](01-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
### Rules for Building High-Performance Code {#Heading5}
|
||||
|
||||
We've got the following rules for creating high-performance software:
|
||||
|
|
@ -135,12 +131,4 @@ together are equivalent to Listing 1.1 except that the entire checksum
|
|||
loop is written in tight assembly code. The assembly language
|
||||
implementation is indeed faster than any of the C versions, as shown in
|
||||
Table 1.1, but it's less than 10 percent faster, and it's still
|
||||
unacceptably slow.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](01-01.html) [Table of Contents](index.html) [Next](01-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
unacceptably slow.
|
||||
14
01-03.md
14
01-03.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](01-02.html) [Table of Contents](index.html) [Next](01-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Listing
|
||||
|
|
@ -251,12 +247,4 @@ Listing 1.1, *even though Listing 1.1 and Listing 1.4 look almost the
|
|||
same*. To the casual observer, **read()** and **getc()** would seem
|
||||
slightly different but pretty much interchangeable, and yet in this
|
||||
application the performance difference between the two is about the same
|
||||
as that between a 4.77 MHz PC and a 16 MHz 386.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](01-02.html) [Table of Contents](index.html) [Next](01-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
as that between a 4.77 MHz PC and a 16 MHz 386.
|
||||
14
01-04.md
14
01-04.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](01-03.html) [Table of Contents](index.html) [Next](01-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
------------------- --------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
 *Make sure you understand what really goes on when you insert a seemingly-innocuous function call into the time-critical portions of your code.*
|
||||
------------------- --------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
|
@ -116,12 +112,4 @@ does *not* run fast enough—13 seconds is a long time. (Stop and wait for
|
|||
long it is.)
|
||||
|
||||
The second reason is the hallmark of the mediocre programmer. Know when
|
||||
optimization matters—and then optimize when it does!
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](01-03.html) [Table of Contents](index.html) [Next](01-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
optimization matters—and then optimize when it does!
|
||||
12
01-05.md
12
01-05.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](01-04.html) [Table of Contents](index.html) [Next](01-06.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
The third reason is often fallacious. C library functions are not always
|
||||
written in assembly, nor are they always particularly well-optimized.
|
||||
(In fact, they're often written for *portability*, which has nothing to
|
||||
|
|
@ -164,11 +160,3 @@ the design has been maxed out.
|
|||
printf("The checksum is: %u\n", Checksum);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](01-04.html) [Table of Contents](index.html) [Next](01-06.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
|
|
|
|||
14
01-06.md
14
01-06.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](01-05.html) [Table of Contents](index.html) [Next](02-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**LISTING 1.7 L1-7.ASM**
|
||||
|
||||
; Assembler subroutine to perform a 16-bit checksum on a block of
|
||||
|
|
@ -110,12 +106,4 @@ be sped up.
|
|||
I'm going to focus on specific ways to create high-performance code from
|
||||
now on. In Chapter 5, we'll continue to look at restartable blocks and
|
||||
internal buffering, in the form of a program that searches files for
|
||||
text strings.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](01-05.html) [Table of Contents](index.html) [Next](02-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
text strings.
|
||||
14
02-01.md
14
02-01.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](01-06.html) [Table of Contents](index.html) [Next](02-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Chapter 2\
|
||||
A World Apart {#Heading1}
|
||||
--------------
|
||||
|
|
@ -102,12 +98,4 @@ transformation that takes place between conception and implementation
|
|||
can reduce performance tremendously; for example, a programmer who
|
||||
implements a routine to search a list of 100,000 sorted items with a
|
||||
linear rather than binary search will end up with a disappointingly slow
|
||||
program.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](01-06.html) [Table of Contents](index.html) [Next](02-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
program.
|
||||
14
02-02.md
14
02-02.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](02-01.html) [Table of Contents](index.html) [Next](02-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
#### Transformation Inefficiencies {#Heading5}
|
||||
|
||||
No matter how well an implementation is derived from the corresponding
|
||||
|
|
@ -101,12 +97,4 @@ out such knowledge.
|
|||
|
||||
------------------- ------------------------------------------------------------------------------------------------------------------------------
|
||||
 *Be forewarned, though: No matter how much you learn about programming the PC in assembly, there's always more to discover.*
|
||||
------------------- ------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](02-01.html) [Table of Contents](index.html) [Next](02-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
------------------- ------------------------------------------------------------------------------------------------------------------------------
|
||||
14
02-03.md
14
02-03.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](02-02.html) [Table of Contents](index.html) [Next](03-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
### The Flexible Mind {#Heading8}
|
||||
|
||||
Is the never-ending collection of information all there is to the
|
||||
|
|
@ -110,12 +106,4 @@ With that in mind, what should the first step be? Development of the
|
|||
flexible mind is an obvious step. Still, the flexible mind is no better
|
||||
than the knowledge at its disposal. The first step in the journey toward
|
||||
mastering optimization at that exalted level, then, would seem to be
|
||||
learning how to learn.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](02-02.html) [Table of Contents](index.html) [Next](03-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
learning how to learn.
|
||||
14
03-01.md
14
03-01.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](02-03.html) [Table of Contents](index.html) [Next](03-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Chapter 3\
|
||||
Assume Nothing {#Heading1}
|
||||
---------------
|
||||
|
|
@ -101,12 +97,4 @@ Listing 3.1 shows 8253-based timer software, consisting of three
|
|||
subroutines: **ZTimerOn, ZTimerOff**, and **ZTimerReport**. For the
|
||||
remainder of this book, I'll refer to these routines collectively as the
|
||||
"Zen timer." C-callable versions of the two precision Zen timers are
|
||||
presented in Chapter K on the companion CD-ROM.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](02-03.html) [Table of Contents](index.html) [Next](03-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
presented in Chapter K on the companion CD-ROM.
|
||||
12
03-02.md
12
03-02.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](03-01.html) [Table of Contents](index.html) [Next](03-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**LISTING 3.1 PZTIMER.ASM**
|
||||
|
||||
; The precision Zen timer (PZTIMER.ASM)
|
||||
|
|
@ -443,11 +439,3 @@
|
|||
|
||||
Code ends
|
||||
end
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](03-01.html) [Table of Contents](index.html) [Next](03-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
|
|
|
|||
14
03-03.md
14
03-03.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](03-02.html) [Table of Contents](index.html) [Next](03-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
#### The Zen Timer Is a Means, Not an End {#Heading5}
|
||||
|
||||
We're going to spend the rest of this chapter seeing what the Zen timer
|
||||
|
|
@ -127,12 +123,4 @@ generate an interrupt; in fact, timer 2 can't do anything but drive the
|
|||
speaker. We need the interrupt generated by the output of timer 0 to
|
||||
tell us when the count has overflowed, and we will see shortly that the
|
||||
timer interrupt also makes it possible to time much longer periods than
|
||||
the Zen timer shown in Listing 3.1 supports.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](03-02.html) [Table of Contents](index.html) [Next](03-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
the Zen timer shown in Listing 3.1 supports.
|
||||
14
03-04.md
14
03-04.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](03-03.html) [Table of Contents](index.html) [Next](03-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
In fact, the Zen timer shown in Listing 3.1 can only time intervals of
|
||||
up to about 54 ms in length, since that is the period of time that can
|
||||
be measured by timer 0 before its count turns over and repeats.
|
||||
|
|
@ -145,12 +141,4 @@ David Miller for passing the idea on to me.)
|
|||
|
||||
You may well want to devise still other approaches better suited to your
|
||||
needs than those I've presented. Go to it! I've just thrown out a few
|
||||
possibilities to get you started.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](03-03.html) [Table of Contents](index.html) [Next](03-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
possibilities to get you started.
|
||||
14
03-05.md
14
03-05.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](03-04.html) [Table of Contents](index.html) [Next](03-06.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
### Notes on the Zen Timer {#Heading10}
|
||||
|
||||
The Zen timer subroutines are designed to be near-called from assembly
|
||||
|
|
@ -160,12 +156,4 @@ execution time of start-up code in the timing interval. That's why the
|
|||
calls to **ZTimerOn** and **ZTimerOff** are in TESTCODE, not in
|
||||
PZTEST.ASM; this way, we have full control over which portion of
|
||||
TESTCODE is timed, and we can keep set-up code and the like out of the
|
||||
timing interval.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](03-04.html) [Table of Contents](index.html) [Next](03-06.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
timing interval.
|
||||
14
03-06.md
14
03-06.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](03-05.html) [Table of Contents](index.html) [Next](03-07.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Listing 3.3 is used by naming it TESTCODE, assembling both Listing 3.2
|
||||
(which includes TESTCODE) and Listing 3.1 with TASM or MASM, and linking
|
||||
the two resulting OBJ files together by way of the Borland orMicrosoft
|
||||
|
|
@ -156,12 +152,4 @@ You should not use the long-period Zen timer to time code that requires
|
|||
interrupts to be disabled for more than 54 ms at a stretch during the
|
||||
timing interval, since when interrupts are disabled the long-period Zen
|
||||
timer is subject to the same 54 ms maximum measurement time as the
|
||||
precision Zen timer.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](03-05.html) [Table of Contents](index.html) [Next](03-07.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
precision Zen timer.
|
||||
12
03-07.md
12
03-07.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](03-06.html) [Table of Contents](index.html) [Next](03-08.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
While permitting the timer interrupt to occur allows long intervals to
|
||||
be timed, that same interrupt makes the long-period Zen timer less
|
||||
accurate than the precision Zen timer, since the time the BIOS spends
|
||||
|
|
@ -704,11 +700,3 @@ computers.
|
|||
|
||||
Code ends
|
||||
end
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](03-06.html) [Table of Contents](index.html) [Next](03-08.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
|
|
|
|||
14
03-08.md
14
03-08.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](03-07.html) [Table of Contents](index.html) [Next](03-09.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Moreover, because it uses an undocumented feature, the timer-stop
|
||||
approach could conceivably cause erratic 8253 operation, which could in
|
||||
turn seriously affect your computer's operation until the next reboot.
|
||||
|
|
@ -128,12 +124,4 @@ linking the two files together by way of the Microsoft or Borland
|
|||
linker. Listing 3.7 shows a batch file, named LZTIME.BAT, which does all
|
||||
of the above, generating and running the executable file LZTEST.EXE.
|
||||
LZTIME.BAT assumes that the file LZTIMER.ASM contains Listing 3.5 and
|
||||
the file LZTEST.ASM contains Listing 3.6.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](03-07.html) [Table of Contents](index.html) [Next](03-09.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
the file LZTEST.ASM contains Listing 3.6.
|
||||
12
03-09.md
12
03-09.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](03-08.html) [Table of Contents](index.html) [Next](03-10.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**LISTING 3.7 LZTIME.BAT**
|
||||
|
||||
echo off
|
||||
|
|
@ -140,11 +136,3 @@ code to use C-style external label names and the small model C code
|
|||
segment. (In C++, use the "C" specifier, as in
|
||||
|
||||
extern "C" ZTimerOn(void);
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](03-08.html) [Table of Contents](index.html) [Next](03-10.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
|
|
|
|||
14
03-10.md
14
03-10.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](03-09.html) [Table of Contents](index.html) [Next](04-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
when declaring the timer routines **extern**, so that name-mangling
|
||||
doesn't occur, and the linker can find the routines' C-style names.)
|
||||
|
||||
|
|
@ -124,12 +120,4 @@ periods.
|
|||
|
||||
Imperfections notwithstanding, the Zen timer is a good tool for
|
||||
exploring C code and x86 family assembly language, and it's a tool we'll
|
||||
use frequently for the remainder of this book.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](03-09.html) [Table of Contents](index.html) [Next](04-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
use frequently for the remainder of this book.
|
||||
14
04-01.md
14
04-01.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](03-10.html) [Table of Contents](index.html) [Next](04-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Chapter 4\
|
||||
In the Lair of the Cycle-Eaters {#Heading1}
|
||||
--------------------------------
|
||||
|
|
@ -150,12 +146,4 @@ only 8 bits wide, as shown in Figure 4.2. The result of this mismatch is
|
|||
simple: Word-sized data can be transferred between the 8088 and memory
|
||||
or peripherals at only one-half the maximum rate of the 8086, which is
|
||||
to say one-half the maximum rate for which the Execution Unit of the
|
||||
8088 was designed.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](03-10.html) [Table of Contents](index.html) [Next](04-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
8088 was designed.
|
||||
14
04-02.md
14
04-02.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](04-01.html) [Table of Contents](index.html) [Next](04-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
\
|
||||
**Figure 4.1** *The location of the major cycle-eaters in the IBM PC.*
|
||||
|
||||
|
|
@ -154,12 +150,4 @@ relevant to real programming problems. On the other hand, optimal code
|
|||
is an elusive thing indeed; by no means should you assume that the code
|
||||
in this book is ideal! Examine it, question it, and improve upon it, for
|
||||
an inquisitive, skeptical mind is an important part of the Zen of
|
||||
assembly optimization.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](04-01.html) [Table of Contents](index.html) [Next](04-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
assembly optimization.
|
||||
14
04-03.md
14
04-03.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[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
|
||||
strive to use byte-sized memory variables whenever possible. That does
|
||||
*not* mean that you should use 2 byte-sized memory accesses to
|
||||
|
|
@ -157,12 +153,4 @@ 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.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](04-02.html) [Table of Contents](index.html) [Next](04-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
that can't be helped.
|
||||
14
04-04.md
14
04-04.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](04-03.html) [Table of Contents](index.html) [Next](04-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
#### Official Execution Times Are Only Part of the Story {#Heading10}
|
||||
|
||||
The sequence of 5 **SHR** instructions in the last example is 10 bytes
|
||||
|
|
@ -147,12 +143,4 @@ instructions which have sucked the prefetch queue dry, so overall
|
|||
performance reflects instruction fetch time. By contrast, each **SHR**
|
||||
in Listing 4.6 follows a **MUL** instruction which leaves the prefetch
|
||||
queue full, so overall performance reflects Execution Unit execution
|
||||
time.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](04-03.html) [Table of Contents](index.html) [Next](04-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
time.
|
||||
14
04-05.md
14
04-05.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](04-04.html) [Table of Contents](index.html) [Next](04-06.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Clearly, either instruction fetch time *or* Execution Unit execution
|
||||
time—or even a mix of the two, if an instruction is partially
|
||||
prefetched—can determine code performance. Some people operate under a
|
||||
|
|
@ -145,12 +141,4 @@ bytes long, thanks to the prefetch queue bottleneck. Short instructions
|
|||
are nonetheless generally faster than long instructions, thanks to the
|
||||
combination of fewer instruction bytes and faster Execution Unit
|
||||
execution times, and should be used as much as possible—just don't
|
||||
expect them to run at their "official" documented speeds.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](04-04.html) [Table of Contents](index.html) [Next](04-06.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
expect them to run at their "official" documented speeds.
|
||||
14
04-06.md
14
04-06.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](04-05.html) [Table of Contents](index.html) [Next](04-07.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
More than anything, the above rules mean using the registers as heavily
|
||||
as possible, both because register-only instructions are short and
|
||||
because they don't perform memory accesses to read or write operands.
|
||||
|
|
@ -128,12 +124,4 @@ occupies cycles during which the 8088 would otherwise be accessing
|
|||
memory.
|
||||
|
||||
\
|
||||
**Figure 4.5** *The PC bus dynamic RAM (DRAM) refresh.*
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](04-05.html) [Table of Contents](index.html) [Next](04-07.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
**Figure 4.5** *The PC bus dynamic RAM (DRAM) refresh.*
|
||||
14
04-07.md
14
04-07.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](04-06.html) [Table of Contents](index.html) [Next](04-08.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
#### The Impact of DRAM Refresh {#Heading17}
|
||||
|
||||
Let's look at examples from opposite ends of the spectrum in terms of
|
||||
|
|
@ -143,12 +139,4 @@ Wait states are cycles during which a bus access by the CPU to a device
|
|||
on the PC's bus is temporarily halted by that device while the device
|
||||
gets ready to complete the read or write. Wait states are well and truly
|
||||
the lowest level of code performance. Everything we have discussed (and
|
||||
will discuss)—even DMA accesses—can be affected by wait states.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](04-06.html) [Table of Contents](index.html) [Next](04-08.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
will discuss)—even DMA accesses—can be affected by wait states.
|
||||
14
04-08.md
14
04-08.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](04-07.html) [Table of Contents](index.html) [Next](04-09.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Wait states exist because the CPU must to be able to coexist with any
|
||||
adapter, no matter how slow (within reason). The 8088 expects to be able
|
||||
to complete each bus access—a memory or I/O read or write—in 4 cycles,
|
||||
|
|
@ -134,12 +130,4 @@ the 8088's already-poor memory access performance in half. Running your
|
|||
code from display memory is sort of like running on a hypothetical
|
||||
8084—an 8086 with a *4-bit* bus. Not recommended!) Given that your code
|
||||
and data reside in normal system memory below the 640K mark, how great
|
||||
an impact does the display adapter cycle-eater have on performance?
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](04-07.html) [Table of Contents](index.html) [Next](04-09.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
an impact does the display adapter cycle-eater have on performance?
|
||||
14
04-09.md
14
04-09.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](04-08.html) [Table of Contents](index.html) [Next](04-10.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
The answer varies considerably depending on what display adapter and
|
||||
what display mode we're talking about. The display adapter cycle-eater
|
||||
is worst with the Enhanced Graphics Adapter (EGA) and the original Video
|
||||
|
|
@ -138,12 +134,4 @@ cycle-eater can *more than double* the execution time of 8088 code!
|
|||
|
||||
Bear in mind that we're talking about a worst case here; the impact of
|
||||
the display adapter cycle-eater is proportional to the percent of time a
|
||||
given code sequence spends accessing display memory.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](04-08.html) [Table of Contents](index.html) [Next](04-10.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
given code sequence spends accessing display memory.
|
||||
14
04-10.md
14
04-10.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](04-09.html) [Table of Contents](index.html) [Next](05-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
 *A line-drawing subroutine, which executes perhaps a dozen instructions for each display memory access, generally loses less performance to the display adapter cycle-eater than does a block-copy or scrolling subroutine that uses **REP MOVS** instructions. Scaled and three-dimensional graphics, which spend a great deal of time performing calculations (often using very slow floating-point arithmetic), tend to suffer less.*
|
||||
------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
|
@ -118,12 +114,4 @@ cycle-eaters vary in importance on later x86-family processors, with
|
|||
some cycle-eaters vanishing altogether and new ones appearing, the
|
||||
concept that understanding these obscure gremlins is a key to
|
||||
performance remains unchanged, as we'll see again and again in later
|
||||
chapters.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](04-09.html) [Table of Contents](index.html) [Next](05-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
chapters.
|
||||
14
05-01.md
14
05-01.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](04-10.html) [Table of Contents](index.html) [Next](05-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Chapter 5\
|
||||
Crossing the Border {#Heading1}
|
||||
--------------------
|
||||
|
|
@ -112,12 +108,4 @@ for the first occurrence of a second string. However, while **strstr()**
|
|||
would work, it isn't ideal for our purposes. The problem is this: Where
|
||||
we want to search a fixed-length buffer for the first occurrence of a
|
||||
string, **strstr()** searches a *string* for the first occurrence of
|
||||
another string.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](04-10.html) [Table of Contents](index.html) [Next](05-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
another string.
|
||||
14
05-02.md
14
05-02.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](05-01.html) [Table of Contents](index.html) [Next](05-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
We could put a zero byte at the end of our buffer to allow **strstr()**
|
||||
to work, but why bother? The **strstr()** function must spend time
|
||||
either checking for the end of the string being searched or determining
|
||||
|
|
@ -115,12 +111,4 @@ Listing 5.1 nicely illustrates the core concept of restartable blocks:
|
|||
Organize your program so that you can do your processing within each
|
||||
block as fast as you could if there were only one block—which is to say
|
||||
at top speed—and make your blocks as large as possible in order to
|
||||
minimize the overhead associated with going from one block to the next.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](05-01.html) [Table of Contents](index.html) [Next](05-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
minimize the overhead associated with going from one block to the next.
|
||||
12
05-03.md
12
05-03.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](05-02.html) [Table of Contents](index.html) [Next](05-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**LISTING 5.1 SEARCH.C**
|
||||
|
||||
/* Program to search the file specified by the first command-line
|
||||
|
|
@ -169,11 +165,3 @@
|
|||
exit(Found); /* Return the found/not found status as the
|
||||
DOS errorlevel */
|
||||
}
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](05-02.html) [Table of Contents](index.html) [Next](05-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
|
|
|
|||
14
05-04.md
14
05-04.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](05-03.html) [Table of Contents](index.html) [Next](05-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
### Interpreting Where the Cycles Go {#Heading8}
|
||||
|
||||
To boost the overall performance of Listing 5.1, I would normally
|
||||
|
|
@ -76,12 +72,4 @@ Likewise, assembly can switch back to **REPNZ SCASB** after a non-match
|
|||
much more quickly than Listing 5.1. The switching overhead is high; when
|
||||
searching a file completely filled with the character z for the string
|
||||
"zy," Listing 5.1 takes almost 1/2 minute, or nearly an order of
|
||||
magnitude longer than when searching a file filled with normal text.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](05-03.html) [Table of Contents](index.html) [Next](05-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
magnitude longer than when searching a file filled with normal text.
|
||||
14
05-05.md
14
05-05.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](05-04.html) [Table of Contents](index.html) [Next](06-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
It might also be worth converting the search engine to assembly for
|
||||
searches performed entirely in memory; with the overhead of file access
|
||||
eliminated, improvements in search-engine performance would translate
|
||||
|
|
@ -67,12 +63,4 @@ itself with greatly improved performance. And when speed is *not* an
|
|||
issue, of course, or in code that's not time-critical, you wouldn't
|
||||
dream of wasting your time on optimization.
|
||||
|
||||
Would you?
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](05-04.html) [Table of Contents](index.html) [Next](06-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
Would you?
|
||||
12
06-01.md
12
06-01.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](05-05.html) [Table of Contents](index.html) [Next](06-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Chapter 6\
|
||||
Looking Past Face Value {#Heading1}
|
||||
------------------------
|
||||
|
|
@ -120,11 +116,3 @@ Or you could let the processor do the arithmetic for you in a single
|
|||
instruction:
|
||||
|
||||
mov al,[bx+si]
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](05-05.html) [Table of Contents](index.html) [Next](06-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
|
|
|
|||
14
06-02.md
14
06-02.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](06-01.html) [Table of Contents](index.html) [Next](07-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
The two approaches are functionally interchangeable but *not* equivalent
|
||||
from a performance standpoint, and which is better depends on the
|
||||
particular context. If it's a one-shot memory access, it's best to let
|
||||
|
|
@ -173,12 +169,4 @@ cycles is a pretty neat trick, even though it works only on a 386 or
|
|||
|
||||
I'd like to extend my thanks to Duane Strong of Metagraphics for his
|
||||
help in brainstorming uses for the 386 version of **LEA** and for
|
||||
pointing out the complications of 486 instruction timings.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](06-01.html) [Table of Contents](index.html) [Next](07-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
pointing out the complications of 486 instruction timings.
|
||||
14
07-01.md
14
07-01.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](06-02.html) [Table of Contents](index.html) [Next](07-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Chapter 7\
|
||||
Local Optimization {#Heading1}
|
||||
-------------------
|
||||
|
|
@ -111,12 +107,4 @@ the relative performances of **LOOP** and **DEC CX/JNZ** on a cached
|
|||
|
||||
------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
 *Things are stranger still for **LOOP**'s relative **JCXZ,** which branches if and only if CX is zero. **JCXZ** is faster than **AND CX,CX/JZ** on the 8088 and 80286, and equivalent on the 80386—but is about twice as slow on the 486!*
|
||||
------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](06-02.html) [Table of Contents](index.html) [Next](07-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
14
07-02.md
14
07-02.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](07-01.html) [Table of Contents](index.html) [Next](07-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
By the way, don't fall victim to the lures of **JCXZ** and do something
|
||||
like this:
|
||||
|
||||
|
|
@ -99,12 +95,4 @@ most that counting cycles could buy us in this case. (All right,
|
|||
already; **LOOPNZ** could be used at the bottom of the loop, and other
|
||||
optimizations are surely possible, but all that won't add up to anywhere
|
||||
near the benefits we're about to see from local optimization, and that's
|
||||
the whole point.)
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](07-01.html) [Table of Contents](index.html) [Next](07-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
the whole point.)
|
||||
14
07-03.md
14
07-03.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](07-02.html) [Table of Contents](index.html) [Next](07-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**LISTING 7.1 L7-1.ASM**
|
||||
|
||||
; Program to illustrate searching through a buffer of a specified
|
||||
|
|
@ -104,12 +100,4 @@ that three-quarters of the **LOOP**s are eliminated. Listings 7.1 and
|
|||
7.2 perform exactly the same task, and they use the same instructions in
|
||||
the loop—the searching algorithm hasn't changed in any way—but we have
|
||||
sequenced the instructions differently in Listing 7.2, and that makes
|
||||
all the difference.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](07-02.html) [Table of Contents](index.html) [Next](07-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
all the difference.
|
||||
14
07-04.md
14
07-04.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](07-03.html) [Table of Contents](index.html) [Next](07-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**LISTING 7.2 L7-2.ASM**
|
||||
|
||||
; Program to illustrate searching through a buffer of a specified
|
||||
|
|
@ -145,12 +141,4 @@ avenues.
|
|||
|
||||
------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
 *The point is simply this: You can gain far more by stepping back a bit and thinking of the fastest overall way for the CPU to perform a task than you can by saving a cycle here or there using different instructions. Try to think at the level of sequences of instructions rather than individual instructions, and learn to treat x86 instructions as building blocks with unique characteristics rather than as instructions dedicated to specific tasks.*
|
||||
------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](07-03.html) [Table of Contents](index.html) [Next](07-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
14
07-05.md
14
07-05.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](07-04.html) [Table of Contents](index.html) [Next](08-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
#### Rotating and Shifting with Tables {#Heading8}
|
||||
|
||||
As another example of local optimization, consider the matter of
|
||||
|
|
@ -175,12 +171,4 @@ the following:
|
|||
ADD AX,1
|
||||
ADC DX,0
|
||||
|
||||
As always, pay attention!
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](07-04.html) [Table of Contents](index.html) [Next](08-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
As always, pay attention!
|
||||
14
08-01.md
14
08-01.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](07-05.html) [Table of Contents](index.html) [Next](08-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Chapter 8\
|
||||
Speeding Up C with Assembly Language {#Heading1}
|
||||
-------------------------------------
|
||||
|
|
@ -114,12 +110,4 @@ your assembly code. True, in assembly you can pass parameters in
|
|||
registers, but the calls and returns themselves are still slow; if the
|
||||
extra cycles they take don't affect performance, then the code they're
|
||||
in probably isn't critical, and perhaps you've chosen to convert too
|
||||
much code to assembly, eh?
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](07-05.html) [Table of Contents](index.html) [Next](08-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
much code to assembly, eh?
|
||||
14
08-02.md
14
08-02.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](08-01.html) [Table of Contents](index.html) [Next](08-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
### Stack Frames Slow So Much {#Heading5}
|
||||
|
||||
C compilers work within the stack frame model, whereby variables reside
|
||||
|
|
@ -130,12 +126,4 @@ Listing 8.1 is the sample C application I'm going to use to examine
|
|||
optimization in action. Listing 8.1 isn't really complete—it doesn't
|
||||
handle the "no-matches" case well, and it assumes that the sum of all
|
||||
matches will fit into an **int—**but it will do just fine as an
|
||||
optimization example.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](08-01.html) [Table of Contents](index.html) [Next](08-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
optimization example.
|
||||
12
08-03.md
12
08-03.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](08-02.html) [Table of Contents](index.html) [Next](08-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**LISTING 8.1 L8-1.C**
|
||||
|
||||
/* Program to search an array spanning a linked list of variable-
|
||||
|
|
@ -176,11 +172,3 @@ instruction can be used.
|
|||
mov WORD PTR [bp-2],di ;IDMatchSum
|
||||
mov WORD PTR [bp-4],dx ;IDMatchCount
|
||||
$FB264:
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](08-02.html) [Table of Contents](index.html) [Next](08-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
|
|
|
|||
12
08-04.md
12
08-04.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](08-03.html) [Table of Contents](index.html) [Next](08-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
It's hard to squeeze much more performance from this code by tweaking
|
||||
it, as exemplified by Listing 8.3, a fine-tuned assembly version of
|
||||
**FindIDAverage** that was produced by looking at the assembly output of
|
||||
|
|
@ -219,11 +215,3 @@ but not a tremendous return for the optimization effort invested.
|
|||
ret
|
||||
_FindIDAverage ENDP
|
||||
end
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](08-03.html) [Table of Contents](index.html) [Next](08-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
|
|
|
|||
14
08-05.md
14
08-05.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](08-04.html) [Table of Contents](index.html) [Next](09-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Listings 8.5 and 8.6 together go the final step and change the rules in
|
||||
favor of assembly language. Listing 8.5 creates the same list of linked
|
||||
blocks as Listing 8.1. However, instead of storing an array of
|
||||
|
|
@ -173,12 +169,4 @@ the low end, resulting in critical code that runs just about as fast as
|
|||
the hardware permits. The only software that can do that is located
|
||||
north of your sternum and slightly aft of your nose. Dust it off and put
|
||||
it to work—and your code will never again be confused with anything by
|
||||
Hamilton, Joe, Frank, eynolds or Bo Donaldson and the Heywoods.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](08-04.html) [Table of Contents](index.html) [Next](09-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
Hamilton, Joe, Frank, eynolds or Bo Donaldson and the Heywoods.
|
||||
12
09-01.md
12
09-01.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](08-05.html) [Table of Contents](index.html) [Next](09-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Chapter 9\
|
||||
Hints My Readers Gave Me {#Heading1}
|
||||
-------------------------
|
||||
|
|
@ -171,11 +167,3 @@ above is faster than this:
|
|||
JNC CopyDone ;done if even copy length
|
||||
MOVSB ;copy the odd byte
|
||||
CopyDone:
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](08-05.html) [Table of Contents](index.html) [Next](09-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
|
|
|
|||
14
09-02.md
14
09-02.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](09-01.html) [Table of Contents](index.html) [Next](09-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
However, it generally is. Sure, if the length is odd, John's approach
|
||||
incurs a penalty approximately equal to the **REP** startup time for
|
||||
**MOVSB**. However, if the length is even, John's approach doesn't
|
||||
|
|
@ -130,12 +126,4 @@ my approach, you'd use **REPNZ SCASB** to scan for each occurrence of
|
|||
would make more sense to scan for "Q," then back up one character and
|
||||
check the whole string when a "Q" is found, as shown in Figure 9.2. "Q"
|
||||
is likely to occur much less often, resulting in many fewer whole-string
|
||||
checks and much faster processing.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](09-01.html) [Table of Contents](index.html) [Next](09-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
checks and much faster processing.
|
||||
12
09-03.md
12
09-03.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](09-02.html) [Table of Contents](index.html) [Next](09-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Listing 9.1 implements the scan-on-first-character approach. Listing 9.2
|
||||
scans for whatever character the caller specifies. Listing 9.3 is a test
|
||||
program used to compare the two approaches. How much difference does
|
||||
|
|
@ -123,11 +119,3 @@ using **REPZ CMPS** to check scanning matches.
|
|||
ret
|
||||
_FindStringendp
|
||||
end
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](09-02.html) [Table of Contents](index.html) [Next](09-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
|
|
|
|||
12
09-04.md
12
09-04.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](09-03.html) [Table of Contents](index.html) [Next](09-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**LISTING 9.2 L9-2.ASM**
|
||||
|
||||
; Searches a text buffer for a text string. Uses REPNZ SCASB to scan
|
||||
|
|
@ -135,11 +131,3 @@
|
|||
strncpy(TempBuffer, MatchPtr, DISPLAY_LENGTH));
|
||||
}
|
||||
}
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](09-03.html) [Table of Contents](index.html) [Next](09-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
|
|
|
|||
14
09-05.md
14
09-05.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](09-04.html) [Table of Contents](index.html) [Next](09-06.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
You'll notice that in Listing 9.2 I didn't use a table of character
|
||||
frequencies in English text to determine the character for which to
|
||||
scan, but rather let the caller make that choice. Each buffer of bytes
|
||||
|
|
@ -111,12 +107,4 @@ divisor, dividing the absolute value of the dividend by the absolute
|
|||
value of the divisor, and applying the stored signs to set the proper
|
||||
signs for the quotient and remainder. There may be more clever ways to
|
||||
produce the same result, by using **IDIV**, for example; if you know of
|
||||
one, drop me a line c/o Coriolis Group Books.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](09-04.html) [Table of Contents](index.html) [Next](09-06.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
one, drop me a line c/o Coriolis Group Books.
|
||||
14
09-06.md
14
09-06.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](09-05.html) [Table of Contents](index.html) [Next](09-07.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**LISTING 9.5 L9-5.ASM**
|
||||
|
||||
; Divides an arbitrarily long unsigned dividend by a 16-bit unsigned
|
||||
|
|
@ -130,12 +126,4 @@ appropriately to produce the desired effect. It can be done: I did it in
|
|||
Turbo C some years back, and trimmed the size of a program (admittedly,
|
||||
a large one) by several K—not bad, when you consider that the "sweet
|
||||
spot" optimization is essentially free, with no code reorganization,
|
||||
change in logic, or heavy thinking involved.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](09-05.html) [Table of Contents](index.html) [Next](09-07.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
change in logic, or heavy thinking involved.
|
||||
14
09-07.md
14
09-07.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](09-06.html) [Table of Contents](index.html) [Next](10-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
#### Hard-Core Cycle Counting {#Heading10}
|
||||
|
||||
Next, we come to an item that cycle counters will love, especially since
|
||||
|
|
@ -140,12 +136,4 @@ Be warned, though, that I've found **OR, AND, ADD**, and the like to be
|
|||
a cycle slower than **MOV** when working with immediate operands on the
|
||||
386 under some circumstances, for reasons that thus far escape me. This
|
||||
just reinforces the first rule of optimization: Measure your code in
|
||||
action, and place not your trust in documented cycle times.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](09-06.html) [Table of Contents](index.html) [Next](10-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
action, and place not your trust in documented cycle times.
|
||||
14
10-01.md
14
10-01.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](09-07.html) [Table of Contents](index.html) [Next](10-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Chapter 10\
|
||||
Patient Coding, Faster Code {#Heading1}
|
||||
----------------------------
|
||||
|
|
@ -126,12 +122,4 @@ Eratosthenes (we'd have been in big trouble if the ancient Greeks had
|
|||
had computers), mainly because after about five minutes of brute
|
||||
force-type work, people's attention gets diverted to other important
|
||||
matters, such as how far a paper airplane will fly from a second-story
|
||||
window.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](09-07.html) [Table of Contents](index.html) [Next](10-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
window.
|
||||
12
10-02.md
12
10-02.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](10-01.html) [Table of Contents](index.html) [Next](10-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Not so nowadays, though. Computers love boring work; they're very
|
||||
patient and disciplined, and, besides, one human year = seven dog years
|
||||
= two zillion computer years. So when we're faced with a problem that
|
||||
|
|
@ -239,11 +235,3 @@ in Listing 10.2.
|
|||
/* Now recursively call this function to continue the process */
|
||||
return(gcd(int1, int2));
|
||||
}
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](10-01.html) [Table of Contents](index.html) [Next](10-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
|
|
|
|||
14
10-03.md
14
10-03.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](10-02.html) [Table of Contents](index.html) [Next](10-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Listing 10.2 repeatedly subtracts iS from iL until iL becomes less than
|
||||
or equal to iS. If iL becomes equal to iS, then that's the GCD;
|
||||
alternatively, if iL becomes *less* than iS, iL and iS switch values,
|
||||
|
|
@ -160,12 +156,4 @@ Microsoft C/C++'s maximum optimization, and also shows the performance
|
|||
of Listing 10.5, an assembly language version of Listing 10.4. Sure, the
|
||||
optimized versions are faster than the unoptimized version of Listing
|
||||
10.4—but the gains are small compared to those realized from the
|
||||
higher-level optimizations in Listings 10.2 through 10.4.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](10-02.html) [Table of Contents](index.html) [Next](10-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
higher-level optimizations in Listings 10.2 through 10.4.
|
||||
14
10-04.md
14
10-04.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](10-03.html) [Table of Contents](index.html) [Next](11-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**LISTING 10.5 L10-5.ASM**
|
||||
|
||||
; Finds and returns the greatest common divisor of two integers.
|
||||
|
|
@ -129,12 +125,4 @@ breakthroughs. Stop, look, listen—and think. Not only will you find that
|
|||
it's a more productive and creative way to program—but you'll also find
|
||||
that it's more fun.
|
||||
|
||||
And think what you could do with all those extra computer years!
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](10-03.html) [Table of Contents](index.html) [Next](11-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
And think what you could do with all those extra computer years!
|
||||
14
11-01.md
14
11-01.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](10-04.html) [Table of Contents](index.html) [Next](11-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Chapter 11\
|
||||
Pushing the 286 and 386 {#Heading1}
|
||||
------------------------
|
||||
|
|
@ -142,12 +138,4 @@ to use byte-sized memory variables in preference to word-sized
|
|||
variables, at least so long as word-sized variables start at even
|
||||
addresses, as we'll see shortly. On the other hand, access to byte-sized
|
||||
variables still isn't any *slower* than access to word-sized variables,
|
||||
so you can use whichever size suits a given task best.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](10-04.html) [Table of Contents](index.html) [Next](11-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
so you can use whichever size suits a given task best.
|
||||
14
11-02.md
14
11-02.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](11-01.html) [Table of Contents](index.html) [Next](11-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
You might think that the elimination of the 8-bit bus cycle-eater would
|
||||
mean that the prefetch queue cycle-eater would also vanish, since on the
|
||||
8088 the prefetch queue cycle-eater is a side effect of the 8-bit bus.
|
||||
|
|
@ -142,12 +138,4 @@ perspective, the 286 in an AT has two-thirds of a 16-bit bus (a 10.7-bit
|
|||
bus?), since every bus access on an AT takes 50 percent longer than it
|
||||
should. A 286 running at 10 MHz *should* be able to access memory at a
|
||||
maximum rate of 1 word every 200 ns; in a 10 MHz AT, however, that rate
|
||||
is reduced to 1 word every 300 ns by the one-wait-state memory.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](11-01.html) [Table of Contents](index.html) [Next](11-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
is reduced to 1 word every 300 ns by the one-wait-state memory.
|
||||
14
11-03.md
14
11-03.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](11-02.html) [Table of Contents](index.html) [Next](11-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
In short, a close relative of our old friend the 8-bit bus
|
||||
cycle-eater—the system memory wait state cycle-eater—haunts us still on
|
||||
all but zero-wait-state 286 and 386 computers, and that means that the
|
||||
|
|
@ -165,12 +161,4 @@ target instruction for any branch effectively cuts the
|
|||
instruction-fetching power of the 286 in half for the first instruction
|
||||
fetch after that branch. While that may not sound like much, you'd be
|
||||
surprised at what it can do to tight loops; in fact, a brief story is in
|
||||
order.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](11-02.html) [Table of Contents](index.html) [Next](11-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
order.
|
||||
14
11-04.md
14
11-04.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](11-03.html) [Table of Contents](index.html) [Next](11-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
When I was developing the Zen timer, I used my trusty 10 MHz 286-based
|
||||
AT clone to verify the basic functionality of the timer by measuring the
|
||||
performance of simple instruction sequences. I was cruising along with
|
||||
|
|
@ -158,12 +154,4 @@ display adapter such as a standard VGA is reasonably well-matched to an
|
|||
8088's memory access speed. Granted, access to a VGA slows the 8088 down
|
||||
considerably—but, as we're about to find out, "considerably" is a
|
||||
relative term. What a VGA does to PC performance is nothing compared to
|
||||
what it does to faster computers.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](11-03.html) [Table of Contents](index.html) [Next](11-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
what it does to faster computers.
|
||||
14
11-05.md
14
11-05.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](11-04.html) [Table of Contents](index.html) [Next](11-06.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Under ideal conditions, a 286 can access memory much, much faster than
|
||||
an 8088. A 10 MHz 286 is capable of accessing a word of system memory
|
||||
every 0.20 ms with **REP MOVSW**, dwarfing the 1 byte every 1.31 µs that
|
||||
|
|
@ -133,12 +129,4 @@ of simple instructions on the 486 and especially on the Pentium.) What's
|
|||
more, both old and new instructions support 32-bit operations on the
|
||||
386. For example, it's relatively simple to copy data in chunks of 4
|
||||
bytes on a 386, even in real mode, by using the **MOVSD** ("move string
|
||||
double") instruction, or to negate a 32-bit value with **NEG eax**.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](11-04.html) [Table of Contents](index.html) [Next](11-06.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
double") instruction, or to negate a 32-bit value with **NEG eax**.
|
||||
12
11-06.md
12
11-06.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](11-05.html) [Table of Contents](index.html) [Next](11-07.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Finally, it's possible in real mode to use the 386's new addressing
|
||||
modes, in which *any* 32-bit general-purpose register or pair of
|
||||
registers can be used to address memory. What's more, multiplication of
|
||||
|
|
@ -116,11 +112,3 @@ Theory confirmed.
|
|||
add dx,100h
|
||||
endm
|
||||
call ZTimerOff
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](11-05.html) [Table of Contents](index.html) [Next](11-07.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
|
|
|
|||
14
11-07.md
14
11-07.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](11-06.html) [Table of Contents](index.html) [Next](11-08.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**LISTING 11.5 L11-5.ASM**
|
||||
|
||||
;
|
||||
|
|
@ -100,12 +96,4 @@ 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
|
||||
can be used in some way to replace **POPF**.
|
||||
14
11-08.md
14
11-08.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](11-07.html) [Table of Contents](index.html) [Next](12-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Well, there's only one instruction other than **POPF** that loads the
|
||||
FLAGS register directly from the stack, and that's **IRET**, which loads
|
||||
the FLAGS register from the stack as it branches, as shown in Figure
|
||||
|
|
@ -112,12 +108,4 @@ it occurs.)
|
|||
|
||||
And now you know the nature of and the workaround for the **POPF** bug.
|
||||
Whether you ever need the workaround or not, it's a neatly packaged
|
||||
example of the tremendous flexibility of the x86 instruction set.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](11-07.html) [Table of Contents](index.html) [Next](12-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
example of the tremendous flexibility of the x86 instruction set.
|
||||
12
12-01.md
12
12-01.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](11-08.html) [Table of Contents](index.html) [Next](12-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Chapter 12\
|
||||
Pushing the 486 {#Heading1}
|
||||
----------------
|
||||
|
|
@ -129,11 +125,3 @@ with this
|
|||
dec cx
|
||||
jnz LoopTop
|
||||
sub si,bx
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](11-08.html) [Table of Contents](index.html) [Next](12-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
|
|
|
|||
14
12-02.md
14
12-02.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](12-01.html) [Table of Contents](index.html) [Next](12-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
which calculates the same sum and leaves the registers in the same state
|
||||
as the first example, but avoids indexed addressing.
|
||||
|
||||
|
|
@ -150,12 +146,4 @@ penalty someday; likewise for the undocumented optimizations I'll
|
|||
describe below. Nonetheless, none of the optimizations I suggest would
|
||||
hurt performance even if the undocumented performance characteristics of
|
||||
the 486 were to vanish, and they certainly will help performance on at
|
||||
least some 486s right now, so I feel they're well worth using.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](12-01.html) [Table of Contents](index.html) [Next](12-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
least some 486s right now, so I feel they're well worth using.
|
||||
14
12-03.md
14
12-03.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](12-02.html) [Table of Contents](index.html) [Next](12-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
There is, of course, no guarantee that I'm entirely correct about the
|
||||
optimizations discussed in this chapter. Without knowing the internals
|
||||
of the 486, all I can do is time code and make inferences from the
|
||||
|
|
@ -150,12 +146,4 @@ the performance dependencies, and I don't plan to; figuring all of them
|
|||
out would be a big, boring job of little value. Basically, on the 486
|
||||
you should concentrate on using those fast core instructions when
|
||||
performance matters, and all the rules I'll discuss do indeed apply to
|
||||
those instructions.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](12-02.html) [Table of Contents](index.html) [Next](12-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
those instructions.
|
||||
14
12-04.md
14
12-04.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](12-03.html) [Table of Contents](index.html) [Next](13-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
You don't need to understand every corner of the 486 universe unless
|
||||
you're a diehard ASMhead who does this stuff for fun. Just learn enough
|
||||
to be able to speed up the key portions of your programs, and spend the
|
||||
|
|
@ -153,12 +149,4 @@ staggeringly fast that carefully crafted 486 code can do more than twice
|
|||
as much per cycle as the best 386 code—which makes it perhaps 50 times
|
||||
as fast as optimized code for the original PC.
|
||||
|
||||
Sometimes it *is* hard to believe we're still in Kansas!
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](12-03.html) [Table of Contents](index.html) [Next](13-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
Sometimes it *is* hard to believe we're still in Kansas!
|
||||
14
13-01.md
14
13-01.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](12-04.html) [Table of Contents](index.html) [Next](13-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Chapter 13\
|
||||
Aiming the 486 {#Heading1}
|
||||
---------------
|
||||
|
|
@ -115,12 +111,4 @@ At this point, Terje had nearly doubled the performance of this code
|
|||
simply by moving one instruction. (Note that swapping the instructions
|
||||
also made it necessary to preload DI at the start of the loop; Listing
|
||||
13.2 is not exactly equivalent to Listing 13.1.) I'll let Terje describe
|
||||
his next optimization in his own words:
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](12-04.html) [Table of Contents](index.html) [Next](13-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
his next optimization in his own words:
|
||||
14
13-02.md
14
13-02.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](13-01.html) [Table of Contents](index.html) [Next](13-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
"When I looked closely as this, I realized that the two cycles for the
|
||||
final **ADD** is just the sum of 1 cycle to load the data from memory,
|
||||
and 1 cycle to add it to DX, so the code could just as well have been
|
||||
|
|
@ -108,12 +104,4 @@ or from memory takes only one cycle. Basically, using **ROR** to access
|
|||
a 16-bit value in the upper half of a 16-bit register is a pretty
|
||||
marginal technique, unless for some reason you can't access memory at
|
||||
all (for example, if you're using BP as a working register, temporarily
|
||||
making the stack frame inaccessible).
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](13-01.html) [Table of Contents](index.html) [Next](13-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
making the stack frame inaccessible).
|
||||
14
13-03.md
14
13-03.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](13-02.html) [Table of Contents](index.html) [Next](13-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
On the 386, **ROR** was the only way to split a 32-bit register into two
|
||||
16-bit registers. On the 486, however, **BSWAP** can not only do the
|
||||
job, but can do it better, because **BSWAP** executes in just one cycle.
|
||||
|
|
@ -102,12 +98,4 @@ slow. But if you're optimizing for the 486, these tidbits can save a few
|
|||
critical cycles—and Lord knows that if you're optimizing for the
|
||||
486—that is, if you need even more performance than you get from
|
||||
unoptimized code on a 486—you almost certainly need all the speed you
|
||||
can get.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](13-02.html) [Table of Contents](index.html) [Next](13-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
can get.
|
||||
14
13-04.md
14
13-04.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](13-03.html) [Table of Contents](index.html) [Next](14-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
### 32-Bit Addressing Modes {#Heading7}
|
||||
|
||||
The 386 and 486 both support 32-bit addressing modes, in which any
|
||||
|
|
@ -103,12 +99,4 @@ capabilities of the Mod-R/M byte, and there's nothing to be done about
|
|||
it, but it's at least worth noting that ESP-based, non-indexed
|
||||
addressing makes for instructions that are a byte larger than other
|
||||
non-indexed addressing (but not any slower; there's no 1-cycle penalty
|
||||
for using ESP as a base register) on the 486.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](13-03.html) [Table of Contents](index.html) [Next](14-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
for using ESP as a base register) on the 486.
|
||||
14
14-01.md
14
14-01.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](13-04.html) [Table of Contents](index.html) [Next](14-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Chapter 14\
|
||||
Boyer-Moore String Searching {#Heading1}
|
||||
-----------------------------
|
||||
|
|
@ -122,12 +118,4 @@ character in turn. In order to get any faster, we'd have to check fewer
|
|||
characters—but we can't do that and still be sure of finding all
|
||||
matches. Can we?
|
||||
|
||||
Actually, yes, we can.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](13-04.html) [Table of Contents](index.html) [Next](14-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
Actually, yes, we can.
|
||||
14
14-02.md
14
14-02.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](14-01.html) [Table of Contents](index.html) [Next](14-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
### The Boyer-Moore Algorithm {#Heading4}
|
||||
|
||||
All our *a priori* knowledge of string searching is stated above, but
|
||||
|
|
@ -117,12 +113,4 @@ skip ahead on all the possible mismatch values.
|
|||
The best case for Boyer-Moore is good indeed: About N/M comparisons are
|
||||
required, where N is the buffer length and M is the pattern length. This
|
||||
reflects the ability of Boyer-Moore to skip ahead by a full pattern
|
||||
length on a complete mismatch.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](14-01.html) [Table of Contents](index.html) [Next](14-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
length on a complete mismatch.
|
||||
14
14-03.md
14
14-03.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](14-02.html) [Table of Contents](index.html) [Next](14-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
How fast *is* Boyer-Moore? Listing 14.1 is a C implementation of
|
||||
Boyer-Moore searching; Listing 14.2 is a test-bed program that searches
|
||||
up to the first 32K of a file for a pattern. Table 14.1 (all times
|
||||
|
|
@ -147,12 +143,4 @@ in most cases than **REPNZ SCASB.** I say this casually now, but not so
|
|||
yesterday, when I had all but concluded that Boyer-Moore was simply
|
||||
inferior on the x86, due to two architectural quirks: the string
|
||||
instructions and slow branch. I had even coined a neat phrase for it:
|
||||
Architecture is destiny. Has a nice ring, doesn't it?
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](14-02.html) [Table of Contents](index.html) [Next](14-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
Architecture is destiny. Has a nice ring, doesn't it?
|
||||
14
14-04.md
14
14-04.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](14-03.html) [Table of Contents](index.html) [Next](14-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**LISTING 14.1 L14-1.C**
|
||||
|
||||
/* Searches a buffer for a specified pattern. In case of a mismatch,
|
||||
|
|
@ -162,12 +158,4 @@ Table 14.1 speak for themselves; Listing 14.3 is more than twice as fast
|
|||
as what I assure you was already a nice, tight assembly implementation
|
||||
(and unrolling **QuickSearchLoop** could boost performance by up to 10
|
||||
percent more). Listing 14.3 is also *four times* faster than **REPNZ
|
||||
SCASB** in one case.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](14-03.html) [Table of Contents](index.html) [Next](14-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
SCASB** in one case.
|
||||
12
14-05.md
12
14-05.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](14-04.html) [Table of Contents](index.html) [Next](14-06.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**LISTING 14.3 L14-3.ASM**
|
||||
|
||||
; Searches a buffer for a specified pattern. In case of a mismatch,
|
||||
|
|
@ -164,11 +160,3 @@
|
|||
ret
|
||||
_FindString endp
|
||||
end
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](14-04.html) [Table of Contents](index.html) [Next](14-06.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
|
|
|
|||
14
14-06.md
14
14-06.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](14-05.html) [Table of Contents](index.html) [Next](15-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Table 14.1 represents a limited and decidedly unscientific comparison of
|
||||
searching techniques. Nonetheless, the overall trend is clear: For all
|
||||
but the shortest patterns, well-implemented Boyer-Moore is generally as
|
||||
|
|
@ -190,12 +186,4 @@ Everything we needed was sitting there all along; we just needed to
|
|||
think to look at it.
|
||||
|
||||
As Yogi Berra might put it, "You don't know what you know until you know
|
||||
it."
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](14-05.html) [Table of Contents](index.html) [Next](15-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
it."
|
||||
14
15-01.md
14
15-01.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](14-06.html) [Table of Contents](index.html) [Next](15-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Chapter 15\
|
||||
Linked Lists and plain Unintended Challenges {#Heading1}
|
||||
---------------------------------------------
|
||||
|
|
@ -140,12 +136,4 @@ structure—but that's an ugly and potentially dangerous trick, and we'll
|
|||
see a better approach next.)
|
||||
|
||||
\
|
||||
**Figure 15.1** *The basic concept of a linked list.*
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](14-06.html) [Table of Contents](index.html) [Next](15-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
**Figure 15.1** *The basic concept of a linked list.*
|
||||
14
15-02.md
14
15-02.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](15-01.html) [Table of Contents](index.html) [Next](15-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**LISTING 15.1 L15-1.C**
|
||||
|
||||
/* Deletes the node in a linked list that follows the indicated node.
|
||||
|
|
@ -151,12 +147,4 @@ themselves to sentinels, but the performance benefits are considerable
|
|||
for those that do.
|
||||
|
||||
\
|
||||
**Figure 15.3** *Representing an empty list.*
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](15-01.html) [Table of Contents](index.html) [Next](15-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
**Figure 15.3** *Representing an empty list.*
|
||||
12
15-03.md
12
15-03.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](15-02.html) [Table of Contents](index.html) [Next](15-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**LISTING 15.5 L15-5.C**
|
||||
|
||||
/* Finds the first node in a value-sorted linked list that
|
||||
|
|
@ -139,11 +135,3 @@ before you write a single line of code.
|
|||
NodePtr->NextNode = NodeToInsert;
|
||||
return(NodePtr);
|
||||
}
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](15-02.html) [Table of Contents](index.html) [Next](15-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
|
|
|
|||
14
15-04.md
14
15-04.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](15-03.html) [Table of Contents](index.html) [Next](16-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**LISTING 15.7 L15-7.ASM**
|
||||
|
||||
; C near-callable assembly function for inserting a new node in a
|
||||
|
|
@ -205,12 +201,4 @@ reads closely enough.
|
|||
Before I end this chapter, let me say that I get a lot of feedback from
|
||||
my readers, and it's much appreciated. Keep those cards, letters, and
|
||||
email messages coming. And if any of you know Jeannie Schweigert, have
|
||||
her drop me a line and let me know how she's doing these days....
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](15-03.html) [Table of Contents](index.html) [Next](16-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
her drop me a line and let me know how she's doing these days....
|
||||
13
16-01.md
13
16-01.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](15-04.html) [Table of Contents](index.html) [Next](16-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Chapter 16\
|
||||
There Ain't No Such Thing as the Fastest Code {#Heading1}
|
||||
----------------------------------------------
|
||||
|
|
@ -179,12 +175,3 @@ Table 16.1 Word count timings.
|
|||
printf("\nTotal words in file: %lu\n", WordCount);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](15-04.html) [Table of Contents](index.html) [Next](16-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
|
|
|
|||
14
16-02.md
14
16-02.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](16-01.html) [Table of Contents](index.html) [Next](16-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Listing 16.2 is Listing 16.1 modified to call a function that scans each
|
||||
block for words, and Listing 16.3 contains an assembly function that
|
||||
counts words. Used together, Listings 16.2 and 16.3 are just about twice
|
||||
|
|
@ -174,12 +170,4 @@ times the performance of the original C code. On a 20 MHz 386, this
|
|||
represents a change from 4.6 to 1.6 seconds, which could be
|
||||
significant—who likes to wait? On an 8088, the improvement in
|
||||
word-counting a large file could easily be 10 or 20 seconds, which is
|
||||
*definitely* significant.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](16-01.html) [Table of Contents](index.html) [Next](16-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
*definitely* significant.
|
||||
14
16-03.md
14
16-03.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](16-02.html) [Table of Contents](index.html) [Next](16-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**LISTING 16.4 L16-4.ASM**
|
||||
|
||||
; Assembly subroutine for Listing 16.2. Scans through Buffer, of
|
||||
|
|
@ -158,12 +154,4 @@ one claimed a speed-up over my assembly word-counting code of more than
|
|||
three times. On top of the three-times speedup over the original C code
|
||||
that I had already realized, we're almost up to an order of magnitude
|
||||
faster. You are, of course, entitled to your own opinion, but *I*
|
||||
consider an order of magnitude to be significant.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](16-02.html) [Table of Contents](index.html) [Next](16-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
consider an order of magnitude to be significant.
|
||||
14
16-04.md
14
16-04.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](16-03.html) [Table of Contents](index.html) [Next](16-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Truth to tell, I didn't expect a three-times speedup; around two times
|
||||
was what I had in mind. Which just goes to show that any code can be
|
||||
made faster than you'd expect, if you think about it long enough and
|
||||
|
|
@ -129,12 +125,4 @@ programmer, was a close third, as shown in Table 16.2, which precedes
|
|||
Listing 16.5. Those three were out ahead of the pack; the fourth-place
|
||||
entry, good as it was (twice as fast as my original code), was twice as
|
||||
slow as David's winning entry, so you can see that David, Dave, and Mick
|
||||
attained a rarefied level of optimization indeed.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](16-03.html) [Table of Contents](index.html) [Next](16-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
attained a rarefied level of optimization indeed.
|
||||
12
16-05.md
12
16-05.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](16-04.html) [Table of Contents](index.html) [Next](16-06.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Table 16.2 has two times for each entry listed: the first value is the
|
||||
overall counting time, including time spent in the main program, disk
|
||||
I/O, and everything else; the second value is the time actually spent
|
||||
|
|
@ -254,11 +250,3 @@ Table 16.2 The top four word-counting entries.
|
|||
.fardata WordTable
|
||||
include qscan3.inc ;built by MAKETAB
|
||||
end
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](16-04.html) [Table of Contents](index.html) [Next](16-06.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
|
|
|
|||
14
16-06.md
14
16-06.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](16-05.html) [Table of Contents](index.html) [Next](16-07.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
### Levels of Optimization {#Heading9}
|
||||
|
||||
Three levels of optimization were evident in the word-counting entries I
|
||||
|
|
@ -80,12 +76,4 @@ short, this is an excellent example of how an hour or so of
|
|||
hand-optimization might accomplish significantly improved performance at
|
||||
a reasonable cost in complexity and time. This level of optimization is
|
||||
adequate for most purposes (and, in truth, is beyond the abilities of
|
||||
most programmers).
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](16-05.html) [Table of Contents](index.html) [Next](16-07.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
most programmers).
|
||||
14
16-07.md
14
16-07.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](16-06.html) [Table of Contents](index.html) [Next](16-08.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**Listing 16.6 OPT2.ASM**
|
||||
|
||||
;
|
||||
|
|
@ -160,12 +156,4 @@ were really looking at an edge triggered device we want to count each
|
|||
time the I'm a character state goes from one to zero. Remembering that
|
||||
XOR on two single-bit values will always return whether the bits are
|
||||
different or the same, I implemented a transition counter. The counter
|
||||
triggers every time a word begins or ends."*
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](16-06.html) [Table of Contents](index.html) [Next](16-08.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
triggers every time a word begins or ends."*
|
||||
14
16-08.md
14
16-08.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](16-07.html) [Table of Contents](index.html) [Next](17-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**Listing 16.7 L16-7.ASM**
|
||||
|
||||
ScanLoop:
|
||||
|
|
@ -163,12 +159,4 @@ that calculates the theoretical maximum performance of native 386
|
|||
word-counting code at 5.5 cycles/byte, which would be significantly
|
||||
faster than David's code. Terry, alas, didn't bother to implement his
|
||||
design, but maybe I'll take a shot at it someday. It'd be fun, for
|
||||
sure—but jeez, I've got *real* work to do!
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](16-07.html) [Table of Contents](index.html) [Next](17-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
sure—but jeez, I've got *real* work to do!
|
||||
14
17-01.md
14
17-01.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](16-08.html) [Table of Contents](index.html) [Next](17-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Chapter 17\
|
||||
The Game of Life {#Heading1}
|
||||
-----------------
|
||||
|
|
@ -90,12 +86,4 @@ we're done using it to calculate the next generation.
|
|||
|
||||
All in all, Listing 17.1 is a clean, compact, and elegant implementation
|
||||
of the Game of Life. Were it not that the code is as slow as molasses,
|
||||
we could stop right here.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](16-08.html) [Table of Contents](index.html) [Next](17-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
we could stop right here.
|
||||
12
17-02.md
12
17-02.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](17-01.html) [Table of Contents](index.html) [Next](17-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**LISTING 17.1 L17-1.CPP**
|
||||
|
||||
/* C++ Game of Life implementation for any mode for which mode set
|
||||
|
|
@ -257,11 +253,3 @@
|
|||
gotoxy(TEXT_X_OFFSET + x, y);
|
||||
puts(text);
|
||||
}
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](17-01.html) [Table of Contents](index.html) [Next](17-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
|
|
|
|||
14
17-03.md
14
17-03.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](17-02.html) [Table of Contents](index.html) [Next](17-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
### Where Does the Time Go? {#Heading5}
|
||||
|
||||
How slow is Listing 17.1? Table 17.1 shows that even on a 486, Listing
|
||||
|
|
@ -157,12 +153,4 @@ with eight completely independent operations, requiring eight calls to
|
|||
In fact, given the nature of cell storage, the eight neighbors are in a
|
||||
fixed relationship to one another, and the addresses and masks of all
|
||||
eight can generally be found very easily via hard-wired offsets and
|
||||
shifts once the address and mask of any one is known.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](17-02.html) [Table of Contents](index.html) [Next](17-04.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
shifts once the address and mask of any one is known.
|
||||
12
17-04.md
12
17-04.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](17-03.html) [Table of Contents](index.html) [Next](17-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
There's a kicker here, though, and that's the counting of neighbors for
|
||||
cells at the edge of the cellmap. When cellmap wrapping is enabled (so
|
||||
that the cellmap becomes essentially a toroid, with each edge joined
|
||||
|
|
@ -203,11 +199,3 @@ improvement.
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](17-03.html) [Table of Contents](index.html) [Next](17-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
|
|
|
|||
14
17-05.md
14
17-05.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](17-04.html) [Table of Contents](index.html) [Next](17-06.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
In Listing 17.3, note the padded cellmap edges, and the alteration of
|
||||
the member functions to compensate for the padding. Also note that the
|
||||
width now has to be a multiple of eight, to facilitate the process of
|
||||
|
|
@ -153,12 +149,4 @@ possible that way.
|
|||
|
||||
------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
 *Once you've reached the point of fine-tuning pointer usage and register variables and the like in C or C++, you've become compiler-dependent; you therefore might as well go to assembly and get the real McCoy.*
|
||||
------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](17-04.html) [Table of Contents](index.html) [Next](17-06.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
14
17-06.md
14
17-06.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](17-05.html) [Table of Contents](index.html) [Next](17-07.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
We're still not ready for assembly, though; what we need is a new
|
||||
perspective that lends itself to vastly better performance in C++. The
|
||||
Life program in the next section is *three to seven times* faster than
|
||||
|
|
@ -117,12 +113,4 @@ time consumed by drawing and text display) than Listing 17.4, which is
|
|||
no slouch. On a 33 MHz 486, Listing 17.5 is about 3.5 times faster than
|
||||
Listing 17.4. This is true even though Listing 17.5 must be compiled
|
||||
using the large model. Imagine that—getting a four times speed-up while
|
||||
switching from the small model to the large model!
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](17-05.html) [Table of Contents](index.html) [Next](17-07.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
switching from the small model to the large model!
|
||||
12
17-07.md
12
17-07.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](17-06.html) [Table of Contents](index.html) [Next](17-08.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**LISTING 17.5 L17-5.CPP**
|
||||
|
||||
/* C++ Game of Life implementation for any mode for which mode set
|
||||
|
|
@ -277,11 +273,3 @@
|
|||
}
|
||||
} while (—init_length);
|
||||
}
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](17-06.html) [Table of Contents](index.html) [Next](17-08.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
|
|
|
|||
14
17-08.md
14
17-08.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](17-07.html) [Table of Contents](index.html) [Next](18-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
The large model is actually not necessary for the 96x96 cellmap in
|
||||
Listing 17.5. However, I was actually more interested in seeing a fast
|
||||
200x200 cellmap, and two 200x200 cellmaps can't fit in a single segment.
|
||||
|
|
@ -75,12 +71,4 @@ for adherence to the rules, read, compiled, linked, run, and judged. I
|
|||
learned a lot—about a lot of things, not the least of which was the
|
||||
process (or maybe the wisdom) of laying down challenges to readers.
|
||||
|
||||
Who won? What did I learn? To find out, read on.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](17-07.html) [Table of Contents](index.html) [Next](18-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
Who won? What did I learn? To find out, read on.
|
||||
12
18-01.md
12
18-01.md
|
|
@ -1,7 +1,3 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](17-08.html) [Table of Contents](index.html) [Next](18-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Chapter 18\
|
||||
It's a plain Wonderful Life {#Heading1}
|
||||
----------------------------
|
||||
|
|
@ -102,11 +98,3 @@ specific "you" may or may not be quite up to the optimizing level of the
|
|||
specific "David Stafford" or "Peter Klerings.")
|
||||
|
||||
Onward to the code.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](17-08.html) [Table of Contents](index.html) [Next](18-02.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue