162 lines
7.6 KiB
HTML
162 lines
7.6 KiB
HTML
<HTML>
|
|
<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: Patient Coding, Faster Code</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.//-->
|
|
<!--CHAPTER=10//-->
|
|
<!--PAGES=200-203//-->
|
|
<!--UNASSIGNED1//-->
|
|
<!--UNASSIGNED2//--></HEAD><BODY LINK=#0000FF ALINK=#000099 VLINK=#0000FF BGCOLOR=#FFFFFF>
|
|
|
|
<CENTER>
|
|
<TABLE BORDER>
|
|
<TR>
|
|
<TD><A HREF="10-03.html">Previous</A></TD>
|
|
<TD><A HREF="index.html">Table of Contents</A></TD>
|
|
<TD><A HREF="11-01.html">Next</A></TD>
|
|
</TR>
|
|
</TABLE>
|
|
</CENTER>
|
|
<P><BR></P>
|
|
<P><B>LISTING 10.5 L10-5.ASM</B></P>
|
|
<!-- CODE //-->
|
|
<PRE>
|
|
; Finds and returns the greatest common divisor of two integers.
|
|
; Uses Euclid’s algorithm: divides the larger integer by the
|
|
; smaller; if the remainder is 0, the smaller integer is the GCD,
|
|
; otherwise the smaller integer becomes the larger integer, the
|
|
; remainder becomes the smaller integer, and the process is
|
|
; repeated. Avoids code recursion.
|
|
;
|
|
;
|
|
;
|
|
; C near-callable as:
|
|
; unsigned int gcd(unsigned int int1, unsigned int int2);
|
|
|
|
; Parameter structure:
|
|
parms struc
|
|
dw ? ;pushed BP
|
|
dw ? ;pushed return address
|
|
int1 dw ? ;integers for which to find
|
|
int2 dw ? ; the GCD
|
|
parms ends
|
|
|
|
.model small
|
|
.code
|
|
public _gcd
|
|
align 2
|
|
_gcd proc near
|
|
push bp ;preserve caller’s stack frame
|
|
mov bp,sp ;set up our stack frame
|
|
push si ;preserve caller’s register variables
|
|
push di
|
|
|
|
;Swap if necessary to make sure that int1 >= int2
|
|
mov ax,int1[bp]
|
|
mov bx,int2[bp]
|
|
cmp ax,bx ;is int1 >= int2?
|
|
jnb IntsSet ;yes, so we’re all set
|
|
xchg ax,bx ;no, so swap int1 and int2
|
|
IntsSet:
|
|
|
|
; Now loop, dividing int1 by int2 and checking the remainder, until
|
|
; the remainder is 0. At each step, if the remainder isn’t 0, assign
|
|
; int2 to int1, and the remainder to int2, then repeat.
|
|
GCDLoop:
|
|
;if the remainder of int1 divided by
|
|
; int2 is 0, then int2 is the gcd
|
|
sub dx,dx ;prepare int1 in DX:AX for division
|
|
div bx ;int1/int2; remainder is in DX
|
|
and dx,dx ;is the remainder zero?
|
|
jz Done ;yes, so int2 (BX) is the gcd
|
|
;no, so move int2 to int1 and the
|
|
; remainder to int2, and repeat the
|
|
; process
|
|
mov ax,bx ;int1 = int2;
|
|
mov bx,dx ;int2 = remainder from DIV
|
|
|
|
;—start of loop unrolling; the above is repeated three times—
|
|
sub dx,dx ;prepare int1 in DX:AX for division
|
|
div bx ;int1/int2; remainder is in DX
|
|
and dx,dx ;is the remainder zero?
|
|
jz Done ;yes, so int2 (BX) is the gcd
|
|
mov ax,bx ;int1 = int2;
|
|
mov bx,dx ;int2 = remainder from DIV
|
|
;—
|
|
sub dx,dx ;prepare int1 in DX:AX for division
|
|
div bx ;int1/int2; remainder is in DX
|
|
and dx,dx ;is the remainder zero?
|
|
jz Done ;yes, so int2 (BX) is the gcd
|
|
mov ax,bx ;int1 = int2;
|
|
mov bx,dx ;int2 = remainder from DIV
|
|
;—
|
|
sub dx,dx ;prepare int1 in DX:AX for division
|
|
div bx ;int1/int2; remainder is in DX
|
|
and dx,dx ;is the remainder zero?
|
|
jz Done ;yes, so int2 (BX) is the gcd
|
|
mov ax,bx ;int1 = int2;
|
|
mov bx,dx ;int2 = remainder from DIV
|
|
;—end of loop unrolling—
|
|
jmp GCDLoop
|
|
|
|
align2
|
|
Done:
|
|
mov ax,bx ;return the GCD
|
|
pop di ;restore caller’s register variables
|
|
pop si
|
|
pop bp ;restore caller’s stack frame
|
|
ret
|
|
_gcd endp
|
|
end
|
|
</PRE>
|
|
<!-- END CODE //-->
|
|
<P>Assembly language optimization is pattern matching on a local scale. Frankly, it’s also the sort of boring, brute-force work that people are lousy at; compilers could out-optimize you at this level with one pass tied behind their back <I>if</I> they knew as much about the code you’re writing as you do, which they don’t.</P>
|
|
<TABLE WIDTH="100%"><TD WIDTH="5%" VALIGN="TOP"><IMG SRC="images/10-03i.jpg"><TD WIDTH="95%"><SMALL><I>Design optimization—conceptual breakthroughs in understanding the relationships between the needs of an application, the nature of the data the application works with, and what the computer can do—is global pattern matching.</I></SMALL>
|
|
</TABLE>
|
|
<P>Computers are <I>much</I> worse at that sort of pattern matching than humans; computers have no way to integrate vast amounts of disparate information, much of it only vaguely defined or subject to change. People, oddly enough, are <I>better</I> at global optimization than at local optimization. For one thing, it’s more interesting. For another, it’s complex and imprecise enough to allow intuition and inspiration, two vastly underrated programming tools, to come to the fore. And, as I pointed out earlier, people tend to perform instantaneous solutions to even the most complex problems, while computers bog down in geometrically or exponentially increasing execution times. Oh, it may take days or weeks for a person to absorb enough information to be able to reach a solution, and the solution may only be near-optimal—but the solution itself (or, at least, each of the pieces of the solution) arrives in a flash.</P>
|
|
<P>Those flashes are your programming pattern matcher doing its job. <I>Your</I> job is to give your pattern matcher the opportunity to get to know each problem and run through it two or three times, from different angles, to see what unexpected solutions it can come up with.</P>
|
|
<P>Pull back the reins a little. Don’t measure progress by lines of code written today; measure it instead by overall progress and by quality. Relax and listen to that quiet inner voice that provides the real 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.</P>
|
|
<P>And think what you could do with all those extra computer years!</P><P><BR></P>
|
|
<CENTER>
|
|
<TABLE BORDER>
|
|
<TR>
|
|
<TD><A HREF="10-03.html">Previous</A></TD>
|
|
<TD><A HREF="index.html">Table of Contents</A></TD>
|
|
<TD><A HREF="11-01.html">Next</A></TD>
|
|
</TR>
|
|
</TABLE>
|
|
</CENTER>
|
|
|
|
<hr width="90%" size="1" noshade>
|
|
<div align="center">
|
|
<font face="Verdana,sans-serif" size="1">Graphics Programming Black Book © 2001 Michael Abrash</font>
|
|
</div>
|
|
<!-- all of the reference materials (books) have the footer and subfoot reveresed -->
|
|
<!-- reference_subfoot = footer -->
|
|
<!-- reference_footer = subfoot -->
|
|
|
|
<!-- BEGIN SUB FOOTER -->
|
|
</BODY>
|
|
</HTML>
|
|
|
|
<!-- END FOOTER -->
|
|
|
|
|