Deduped images

This commit is contained in:
James Gregory 2013-12-30 12:25:34 +11:00
commit 9e52de9586
233 changed files with 128 additions and 128 deletions

View file

@ -60,7 +60,7 @@ jz SkipLoop ;If field is 0, don’t bother
<P>One level at which assembly language programming pays off handsomely is that of <I>local optimization;</I> that is, selecting the best <I>sequence</I> of instructions for a task. The key to local optimization is viewing the 80x86 instruction set as a set of building blocks, each with unique characteristics. Your job is to sequence those blocks so that they perform well. It doesn&#146;t matter what the instructions are intended to do or what their names are; all that matters is what they <I>do.</I></P>
<P>Our discussion of <B>LOOP</B> versus <B>DEC/JNZ</B> is an excellent example of optimization by cycle counting. It&#146;s worth knowing, but once you&#146;ve learned it, you just routinely use <B>DEC/JNZ</B> at the bottom of loops in 386/486-specific code, and that&#146;s that. Besides, you&#146;ll save at most a few cycles each time, and while that helps a little, it&#146;s not going to make all <I>that</I> much difference.</P>
<P>Now let&#146;s step back for a moment, and with no preconceptions consider what the x86 instruction set can do for us. The bulk of the time with both <B>LOOP</B> and <B>DEC/JNZ</B> is taken up by branching, which just happens to be one of the slowest aspects of every processor in the x86 family, and the rest is taken up by decrementing the count register and checking whether it&#146;s zero. There may be ways to perform those tasks a little faster by selecting different instructions, but they can get only so fast, and branching can&#146;t even get all that fast.</P>
<TABLE WIDTH="100%"><TD ALIGN="LEFT" VALIGN="TOP" WIDTH="5%"><IMG SRC="images/07-04i.jpg"><TD ALIGN="LEFT" VALIGN="TOP" WIDTH="95%"><SMALL><I>The trick, then, is not to find the fastest way to decrement a count and branch conditionally, but rather to figure out how to accomplish the same result without decrementing or branching as often. Remember the Kobiyashi Maru problem in</I> Star Trek<I>?The same principle applies here: Redefine the problem to one that offers better solutions.</I></SMALL>
<TABLE WIDTH="100%"><TD ALIGN="LEFT" VALIGN="TOP" WIDTH="5%"><IMG SRC="images/i.jpg"><TD ALIGN="LEFT" VALIGN="TOP" WIDTH="95%"><SMALL><I>The trick, then, is not to find the fastest way to decrement a count and branch conditionally, but rather to figure out how to accomplish the same result without decrementing or branching as often. Remember the Kobiyashi Maru problem in</I> Star Trek<I>?The same principle applies here: Redefine the problem to one that offers better solutions.</I></SMALL>
</TABLE>
<P>Consider Listing 7.1, which searches a buffer until either the specified byte is found, a zero byte is found, or the specified number of characters have been checked. Such a function would be useful for scanning up to a maximum number of characters in a zero-terminated buffer. Listing 7.1, which uses <B>LOOP</B> in the main loop, performs a search of the sample string for a period (&#145;.&#146;) in 170 &#181;s on a 20 MHz cached 386.</P>
<P>When the <B>LOOP</B> in Listing 7.1 is replaced with <B>DEC CX/JNZ,</B> performance improves to 168 &#181;s, less than 2 percent faster than Listing 7.1. Actually, instruction fetching, instruction alignment, cache characteristics, or something similar is affecting these results; I&#146;d expect a slightly larger improvement&#151;around 7 percent&#151;but that&#146;s the most that counting cycles could buy us in this case. (All right, already; <B>LOOPNZ</B> could be used at the bottom of the loop, and other optimizations are surely possible, but all that won&#146;t add up to anywhere near the benefits we&#146;re about to see from local optimization, and that&#146;s the whole point.)</P><P><BR></P>