Strip comments and inline ids onto h*
This commit is contained in:
parent
1997a7846d
commit
0f5f617adb
362 changed files with 2519 additions and 6694 deletions
41
04-03.html
41
04-03.html
|
|
@ -10,16 +10,9 @@
|
|||
<meta name="vspubdate" content="07/01/97" />
|
||||
<meta name="vscategory" content="Web and Software Development: Game Development,Web and Software Development: Graphics and Multimedia Development" />
|
||||
|
||||
<title>Michael Abrash's Graphics Programming Black Book Special Edition: In the Lair of the Cycle-Eaters</title><!-- HEADER -->
|
||||
<!-- Empty Reference Subhead -->
|
||||
<!--ISBN=1576101746//-->
|
||||
<!--TITLE=Michael Abrash's Graphics Programming Black Book Special Edition//-->
|
||||
<!--AUTHOR=Michael Abrash//-->
|
||||
<!--PUBLISHER=The Coriolis Group, Inc.//-->
|
||||
<title>Michael Abrash's Graphics Programming Black Book Special Edition: In the Lair of the Cycle-Eaters</title>
|
||||
<meta name="chapter" content="04" />
|
||||
<meta name="pages" content="084-087" />
|
||||
<!--UNASSIGNED1//-->
|
||||
<!--UNASSIGNED2//-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
@ -37,22 +30,22 @@
|
|||
|
||||
<p><br /></p>
|
||||
|
||||
<p>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 <i>not</i> mean that you should use 2 byte-sized memory accesses to manipulate a word-sized memory variable in preference to 1 word-sized memory access, as, for instance,</p><!-- CODE SNIP //-->
|
||||
<p>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 <i>not</i> mean that you should use 2 byte-sized memory accesses to manipulate a word-sized memory variable in preference to 1 word-sized memory access, as, for instance,</p>
|
||||
<pre>
|
||||
mov dl,byte ptr [MemVar]
|
||||
mov dh,byte ptr [MemVar+1]
|
||||
</pre><!-- END CODE SNIP //-->
|
||||
</pre>
|
||||
|
||||
<p>versus:</p><!-- CODE SNIP //-->
|
||||
<p>versus:</p>
|
||||
<pre>
|
||||
mov dx,word ptr [MemVar]
|
||||
</pre><!-- END CODE SNIP //-->
|
||||
</pre>
|
||||
|
||||
<p>Recall that every access to a memory byte takes at least 4 cycles; that limitation is built right into the 8088. The 8088 is also built so that the second byte-sized memory access to a 16-bit memory variable takes just those 4 cycles and no more. There’s no way you can manipulate the second byte of a word-sized memory variable faster with a second separate byte-sized instruction in less than 4 cycles. As a matter of fact, you’re bound to access that second byte much more slowly with a separate instruction, thanks to the overhead of instruction fetching and execution, address calculation, and the like.</p>
|
||||
|
||||
<p>For example, consider Listing 4.3, which performs 1,000 word-sized reads from memory. This code runs in 3.77 µs per word read on a 4.77 MHz 8088. That’s 45 percent faster than the 5.49 µs per word read of Listing 4.4, which reads the same 1,000 words as Listing 4.3 but does so with 2,000 byte-sized reads. Both listings perform exactly the same number of memory accesses—2,000 accesses, each byte-sized, as all 8088 memory accesses must be. (Remember that the Bus Interface Unit must perform two byte-sized memory accesses in order to handle a word-sized memory operand.) However, Listing 4.3 is considerably faster because it expends only 4 additional cycles to read the second byte of each word, while Listing 4.4 performs a second <b>LODSB,</b> requiring 13 cycles, to read the second byte of each word.</p>
|
||||
|
||||
<p><b>LISTING 4.3 LST4-3.ASM</b></p><!-- CODE SNIP //-->
|
||||
<p><b>LISTING 4.3 LST4-3.ASM</b></p>
|
||||
<pre>
|
||||
; Measures the performance of reading 1,000 words
|
||||
; from memory with 1,000 word-sized accesses.
|
||||
|
|
@ -62,9 +55,9 @@ mov dx,word ptr [MemVar]
|
|||
call ZTimerOn
|
||||
rep lodsw
|
||||
call ZTimerOff
|
||||
</pre><!-- END CODE SNIP //-->
|
||||
</pre>
|
||||
|
||||
<p><b>LISTING 4.4 LST4-4.ASM</b></p><!-- CODE SNIP //-->
|
||||
<p><b>LISTING 4.4 LST4-4.ASM</b></p>
|
||||
<pre>
|
||||
; Measures the performance of reading 1000 words
|
||||
; from memory with 2,000 byte-sized accesses.
|
||||
|
|
@ -74,7 +67,7 @@ mov dx,word ptr [MemVar]
|
|||
call ZTimerOn
|
||||
rep lodsb
|
||||
call ZTimerOff
|
||||
</pre><!-- END CODE SNIP //-->
|
||||
</pre>
|
||||
|
||||
<p>In short, if you must perform a 16-bit memory access, let the 8088 break the access into two byte-sized accesses for you. The 8088 is more efficient at that task than your code can possibly be.</p>
|
||||
|
||||
|
|
@ -86,7 +79,7 @@ mov dx,word ptr [MemVar]
|
|||
|
||||
<p>Yes and no. It’s true that in general we know approximately how much longer a given instruction will take to execute with a word-sized memory operand than with a byte-sized operand, although the dynamic RAM refresh and wait state cycle-eaters (which I’ll cover a little later) can raise the cost of the 8-bit bus cycle-eater considerably. However, <i>all</i> word-sized memory accesses lose 4 cycles to the 8-bit bus cycle-eater, and there’s one sort of word-sized memory access we haven’t discussed yet: instruction fetching. The ugliest manifestation of the 8-bit bus cycle-eater is in fact the prefetch queue cycle-eater.</p>
|
||||
|
||||
<h3><a id="Heading9"></a>The Prefetch Queue Cycle-Eater</h3>
|
||||
<h3 id="Heading9">The Prefetch Queue Cycle-Eater</h3>
|
||||
|
||||
<p>In an 8088 context, here’s the prefetch queue cycle-eater in a nutshell: The 8088’s 8-bit external data bus keeps the Bus Interface Unit from fetching instruction bytes as fast as the 16-bit Execution Unit can execute them, so the Execution Unit often lies idle while waiting for the next instruction byte to be fetched.</p>
|
||||
|
||||
|
|
@ -96,19 +89,19 @@ mov dx,word ptr [MemVar]
|
|||
|
||||
<p>Clearly, then, the prefetch queue cycle-eater is nothing more than one aspect of the 8-bit bus cycle-eater. 8088 code often runs at less than the Execution Unit’s maximum speed because the 8-bit data bus can’t keep up with the demand for instruction bytes. That’s straightforward enough—so why all the fuss about the prefetch queue cycle-eater?</p>
|
||||
|
||||
<p>What makes the prefetch queue cycle-eater tricky is that it’s undocumented and unpredictable. That is, with a word-sized memory access, such as</p><!-- CODE SNIP //-->
|
||||
<p>What makes the prefetch queue cycle-eater tricky is that it’s undocumented and unpredictable. That is, with a word-sized memory access, such as</p>
|
||||
<pre>
|
||||
mov [bx],ax
|
||||
</pre><!-- END CODE SNIP //-->
|
||||
</pre>
|
||||
|
||||
<p>it’s well-documented that an extra 4 cycles will always be required to write the upper byte of AX to memory. Not so with the prefetch queue cycle-eater lurking nearby. For instance, the instructions</p><!-- CODE SNIP //-->
|
||||
<p>it’s well-documented that an extra 4 cycles will always be required to write the upper byte of AX to memory. Not so with the prefetch queue cycle-eater lurking nearby. For instance, the instructions</p>
|
||||
<pre>
|
||||
shr ax,1
|
||||
shr ax,1
|
||||
shr ax,1
|
||||
shr ax,1
|
||||
shr ax,1
|
||||
</pre><!-- END CODE SNIP //-->
|
||||
</pre>
|
||||
|
||||
<p>should execute in 10 cycles, since each <b>SHR</b> takes 2 cycles to execute, according to Intel’s specifications. Those specifications contain Intel’s official instruction execution times, but in this case—and in many others—the specifications are drastically wrong. Why? Because they describe execution time <i>once an instruction reaches the prefetch queue.</i> They say nothing about whether a given instruction will be in the prefetch queue when it’s time for that instruction to run, or how long it will take that instruction to reach the prefetch queue if it’s not there already. Thanks to the low performance of the 8088’s external data bus, that’s a glaring omission—but, alas, an unavoidable one. Let’s look at why the official execution times are wrong, and why that can’t be helped.</p>
|
||||
|
||||
|
|
@ -129,10 +122,6 @@ shr ax,1
|
|||
|
||||
<div align="center">
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
</div><!-- all of the reference materials (books) have the footer and subfoot reveresed -->
|
||||
<!-- reference_subfoot = footer -->
|
||||
<!-- reference_footer = subfoot -->
|
||||
<!-- BEGIN SUB FOOTER -->
|
||||
<!-- END FOOTER -->
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Reference in a new issue