120 lines
7 KiB
HTML
120 lines
7 KiB
HTML
<!DOCTYPE html>
|
|
|
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
<head>
|
|
<meta name="vsisbn" content="1576101746" />
|
|
<meta name="vstitle" content="Michael Abrash's Graphics Programming Black Book, Special Edition" />
|
|
<meta name="vsauthor" content="Michael Abrash" />
|
|
<meta name="vspublisher" content="The Coriolis Group" />
|
|
<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: Zenning and the Flexible Mind</title>
|
|
<meta name="chapter" content="22" />
|
|
<meta name="pages" content="413-417" />
|
|
</head>
|
|
|
|
<body>
|
|
<center>
|
|
<table border="1">
|
|
<tr>
|
|
<td>
|
|
<a href="21-05.html">Previous</a>
|
|
</td>
|
|
|
|
<td>
|
|
<a href="index.html">Table of Contents</a>
|
|
</td>
|
|
|
|
<td>
|
|
<a href="22-02.html">Next</a>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</center>
|
|
|
|
<h2 id="Heading1">Chapter 22<br />
|
|
Zenning and the Flexible Mind</h2>
|
|
|
|
<h3 id="Heading2">Taking a Spin through What You’ve Learned</h3>
|
|
|
|
<p>And so we come to the end of our journey; for now, at least. What follows is a modest bit of optimization, one which originally served to show readers of <i>Zen of Assembly Language</i> that they had learned more than just bits and pieces of knowledge; that they had also begun to learn how to apply the flexible mind—unconventional, broadly integrative thinking—to approaching high-level optimization at the algorithmic and program design levels. You, of course, need no such reassurance, having just spent 21 chapters learning about the flexible mind in many guises, but I think you’ll find this example instructive nonetheless. Try to stay ahead as the level of optimization rises from instruction elimination to instruction substitution to more creative solutions that involve broader understanding and redesign. We’ll start out by compacting individual instructions and bits of code, but by the end we’ll come up with a solution that involves the very structure of the subroutine, with each instruction carefully integrated into a remarkably compact whole. It’s a neat example of how optimization operates at many levels, some much less determininstic than others—and besides, it’s just plain fun.</p>
|
|
|
|
<p>Enjoy!</p>
|
|
|
|
<h3 id="Heading3">Zenning</h3>
|
|
|
|
<p>In Jeff Duntemann’s excellent book <i>Borland Pascal From Square One</i> (Random House, 1993), there’s a small assembly subroutine that’s designed to be called from a Turbo Pascal program in order to fill the screen or a systemscreen buffer with a specified character/attribute pair in text mode. This subroutine involves only 21 instructions and works perfectly well; however, with what we know, we can compact the subroutine tremendously and speed it up a bit as well. To coin a verb, we can “Zen” this already-tight assembly code to an astonishing degree. In the process, I hope you’ll get a feel for how advanced your assembly skills have become.</p>
|
|
|
|
<p>Jeff’s original code follows as Listing 22.1 (with some text converted to lowercase in order to match the style of this book), but the comments are mine.</p>
|
|
|
|
<p><b>LISTING 22.1 L22-1.ASM</b></p>
|
|
<pre>
|
|
OnStack struc ;data that’s stored on the stack after PUSH BP
|
|
OldBP dw ? ;caller’s BP
|
|
RetAddr dw ? ;return address
|
|
Filler dw ? ;character to fill the buffer with
|
|
Attrib dw ? ;attribute to fill the buffer with
|
|
BufSize dw ? ;number of character/attribute pairs to fill
|
|
BufOfs dw ? ;buffer offset
|
|
BufSeg dw ? ;buffer segment
|
|
EndMrk db ? ;marker for the end of the stack frame
|
|
OnStack ends
|
|
;
|
|
ClearS proc near
|
|
push bp ;save caller’s BP
|
|
mov bp,sp ;point to stack frame
|
|
cmp word ptr [bp].BufSeg,0 ;skip the fill if a null
|
|
jne Start ; pointer is passed
|
|
cmp word ptr [bp].BufOfs,0
|
|
je Bye
|
|
Start: cld ;make STOSW count up
|
|
mov ax,[bp].Attrib ;load AX with attribute parameter
|
|
and ax,0ff00h ;prepare for merging with fill char
|
|
mov bx,[bp].Filler ;load BX with fill char
|
|
and bx,0ffh ;prepare for merging with attribute
|
|
or ax,bx ;combine attribute and fill char
|
|
mov bx,[bp].BufOfs ;load DI with target buffer offset
|
|
mov di,bx
|
|
mov bx,[bp].BufSeg ;load ES with target buffer segment
|
|
mov es,bx
|
|
mov cx,[bp].BufSize ;load CX with buffer size
|
|
rep stosw ;fill the buffer
|
|
Bye:mov sp,bp ;restore original stack pointer
|
|
pop bp ; and caller’s BP
|
|
ret EndMrk-RetAddr-2 ;return, clearing the parms from the stack
|
|
ClearS endp
|
|
</pre>
|
|
|
|
<p>The first thing you’ll notice about Listing 22.1 is that <b>ClearS</b> uses a <b>REP STOSW</b> instruction. That means that we’re not going to improve performance by any great amount, no matter how clever we are. While we can eliminate some cycles, the bulk of the work in <b>ClearS</b> is done by that one repeated string instruction, and there’s no way to improve on that.</p>
|
|
|
|
<p>Does that mean that Listing 22.1 is as good as it can be? Hardly. While the speed of <b>ClearS</b> is very good, there’s another side to the optimization equation: size. The whole of <b>ClearS</b> is 52 bytes long as it stands—but, as we’ll see, that size is hardly set in stone.</p>
|
|
|
|
<p>Where do we begin with <b>ClearS</b>? For starters, there’s an instruction in there that serves no earthly purpose—<b>MOV SP,BP</b>. SP is guaranteed to be equal to BP at that point anyway, so why reload it with the same value? Removing that instruction saves us two bytes.</p>
|
|
|
|
<p>Well, that was certainly easy enough! We’re not going to find any more totally non-functional instructions in <b>ClearS</b>, however, so let’s get on to some serious optimizing. We’ll look first for cases where we know of better instructions for particular tasks than those that were chosen. For example, there’s no need to load any register, whether segment or general, through BX; we can eliminate two instructions by loading ES and DI directly as shown in Listing 22.2.</p>
|
|
|
|
<center>
|
|
<table border="1">
|
|
<tr>
|
|
<td>
|
|
<a href="21-05.html">Previous</a>
|
|
</td>
|
|
|
|
<td>
|
|
<a href="index.html">Table of Contents</a>
|
|
</td>
|
|
|
|
<td>
|
|
<a href="22-02.html">Next</a>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</center>
|
|
<hr width="90%" size="1" noshade="noshade" />
|
|
|
|
<div align="center">
|
|
Graphics Programming Black Book © 2001 Michael Abrash
|
|
</div>
|
|
</body>
|
|
</html>
|