abrash-black-book/15-04.html

250 lines
9.8 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: Linked Lists and Unintended Challenges</title>
<meta name="chapter" content="15" />
<meta name="pages" content="290-293" />
</head>
<body>
<center>
<table border="1">
<tr>
<td>
<a href="15-03.html">Previous</a>
</td>
<td>
<a href="index.html">Table of Contents</a>
</td>
<td>
<a href="16-01.html">Next</a>
</td>
</tr>
</table>
</center>
<p><b>LISTING 15.7 L15-7.ASM</b></p>
<pre>
; C near-callable assembly function for inserting a new node in a
; linked list sorted by ascending order of the Value field. The list
; is circular; that is, it has a dummy node as both the head and the
; tail of the list. The dummy node is a sentinel, containing the
; largest possible Value field setting. Tested with TASM.
MAX_TEXT_LENGTH equ 100 ;longest allowed Text field
SENTINEL equ 32767 ;largest possible Value field
LinkNode struc
NextNode dw ?
Value dw ?
Text db MAX_TEXT_LENGTH+1 dup(?)
;*** Any number of additional data fields may by present ***
LinkNode ends
.model small
.code
; Inserts the specified node into a ascending-value-sorted linked
; list, such that value-sorting is maintained. Returns a pointer to
; the node after which the new node is inserted.
; C near-callable as:
; struct LinkNode *InsertNodeSorted(struct LinkNode *HeadOfListNode,
; struct LinkNode *NodeToInsert)
parms struc
dw 2 dup (?) ;pushed return address &amp; BP
HeadOfListNode dw ? ;pointer to head node of list
NodeToInsert dw ? ;pointer to node to insert
parms ends
public _InsertNodeSorted
_InsertNodeSorted proc near
push bp
mov bp,sp ;point to stack frame
push si ;preserve register vars
push di
mov si,[bp].NodeToInsert ;point to node to insert
mov ax,[si].Value ;search value
mov di,[bp].HeadOfListNode ;point to linked list in
; which to insert
SearchLoop:
mov bx,di ;advance to the next node
mov di,[bx].NextNode ;point to following node
cmp [di].Value,ax ;is the following node's
; value less than the value
; from the node to insert?
jl SearchLoop ;yes, so continue searching
;no, so we have found our
; insert point
mov ax,[bx].NextNode ;link the new node between
mov [si].NextNode,ax ; the current node and the
mov [bx].NextNode,si ; following node
mov ax,bx ;return pointer to node
; after which we inserted
pop di ;restore register vars
pop si
pop bp
ret
_InsertNodeSorted endp
end
</pre>
<p><b>LISTING 15.8 L15-8.C</b></p>
<pre>
/* Sample linked list program. Tested with Borland C++. */
#include &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;
#include &lt;conio.h&gt;
#include &lt;ctype.h&gt;
#include &lt;string.h&gt;
#include &ldquo;llist.h&rdquo;
void main()
{ int Done = 0, Char, TempValue;
struct LinkNode *TempPtr, *ListPtr, *TempPtr2;
char TempBuffer[MAX_TEXT_LENGTH+3];
if ((ListPtr = InitLinkedList()) == NULL) {
printf(&ldquo;Out of memory\n&rdquo;);
exit(1);
}
while (!Done) {
printf(&ldquo;\nA=add; D=delete; F=find; L=list all; Q=quit\n&gt;&rdquo;);
Char = toupper(getche());
printf(&ldquo;\n&rdquo;);
switch (Char) {
case 'A': /* add a node */
if ((TempPtr = malloc(sizeof(struct LinkNode))) == NULL)
{
printf(&ldquo;Out of memory\n );
exit(1);
}
printf(&ldquo;Node value: &rdquo;);
scanf(&ldquo;%d&rdquo;, &amp;TempPtr-&gt;Value);
if ((FindNodeBeforeValue(ListPtr,TempPtr-&gt;Value))!=NULL)
{ printf(&ldquo;*** value already in list; try again ***\n&rdquo;);
free(TempPtr);
} else {printf(&ldquo;Node text: &rdquo;);
TempBuffer[0] = MAX_TEXT_LENGTH;
cgets(TempBuffer);
strcpy(TempPtr-&gt;Text, &amp;TempBuffer[2]);
InsertNodeSorted(ListPtr, TempPtr);
printf(&ldquo;\n&rdquo;);
}
break;
case 'D': /* delete a node */
printf(&ldquo;Value field of node to delete: &rdquo;);
scanf(&ldquo;%d&rdquo;, &amp;TempValue);
if ((TempPtr = FindNodeBeforeValue(ListPtr, TempValue))
!= NULL) {
TempPtr2 = TempPtr-&gt;NextNode; /* -&gt; node to delete */
DeleteNodeAfter(TempPtr); /* delete it */
free(TempPtr2); /* free its memory */
} else {
printf(&ldquo;*** no such value field in list ***\n&rdquo;)
break;
case 'F': /* find a node */
printf(&ldquo;Value field of node to find: &rdquo;);
scanf(&ldquo;%d&rdquo;, &amp;TempValue);
if ((TempPtr = FindNodeBeforeValue(ListPtr, TempValue))
!= NULL)
printf(&ldquo;Value: %d\nText: %s\n&rdquo;,
TempPtr-&gt;NextNode-&gt;Value, TempPtr-&gt;NextNode-&gt;Text);
else
printf(&ldquo;*** no such value field in list ***\n&rdquo;);
break;
case 'L': /* list all nodes */
TempPtr = ListPtr-&gt;NextNode; /* point to first node */
if (TempPtr == ListPtr) { /* empty if at sentinel */
printf(&ldquo;*** List is empty ***\n&rdquo;);
} else {
do {printf(&ldquo;Value: %d\n Text: %s\n&rdquo;, TempPtr-&gt;Value,
TempPtr-&gt;Text);
TempPtr = TempPtr-&gt;NextNode;
} while (TempPtr != ListPtr);
}
break;
case 'Q':
Done = 1;
break;
default:
break;
}
}
}
</pre>
<h3 id="Heading6">Hi/Lo in 24 Bytes</h3>
<p>In one of my <i>PC TECHNIQUES</i> &ldquo;Pushing the Envelope&rdquo; columns, I passed along one of David Stafford&rsquo;s fiendish programming puzzles: Write a C-callable function to find the greatest or smallest unsigned <b>int</b>. Not a big deal&mdash;except that David had <i>already</i> done it in 24 bytes, so the challenge was to do it in 24 bytes or less.</p>
<p>Such routines soon began coming at me from all angles. However (and I hate to say this because some of my correspondents were <i>very</i> pleased with the thought that they had bested David), no one has yet met the challenge&mdash;because most of you folks missed a key point. When David said, &ldquo;Write a function to find the greatest or smallest unsigned <b>int</b> in 24 bytes or less,&rdquo; he meant, &ldquo;Write the <b>hi</b> and the <b>lo</b> functions in 24 bytes or less&mdash;<i>combined</i>.&rdquo;</p>
<p>Oh.</p>
<p>Yes, a 24-byte hi/lo function is possible, anatomically improbable as it might seem. Which I guess goes to show that when one of David&rsquo;s puzzles seems less than impossible, odds are you&rsquo;re missing something. Listing 15.9 is David&rsquo;s 24-byte solution, from which a lot may be learned if one reads closely enough.</p>
<p><b>LISTING 15.9 L15-9.ASM</b></p>
<pre>
; Find the greatest or smallest unsigned int.
; C callable (small model); 24 bytes.
; By David Stafford.
; unsigned hi( int num, unsigned a[] );
; unsigned lo( int num, unsigned a[] );
public _hi, _lo
_hi: db 0b9h ;mov cx,immediate
_lo: xor cx,cx
pop ax ;get return address
pop dx ;get count
pop bx ;get pointer
push bx ;restore pointer
push dx ;restore count
push ax ;restore return address
save: mov ax,[bx]
top: cmp ax,[bx]
jcxz around
cmc
around: ja save
inc bx
inc bx
dec dx
jnz top
ret
</pre>
<p>Before I end this chapter, let me say that I get a lot of feedback from my readers, and it&rsquo;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&rsquo;s doing these days....</p>
<center>
<table border="1">
<tr>
<td>
<a href="15-03.html">Previous</a>
</td>
<td>
<a href="index.html">Table of Contents</a>
</td>
<td>
<a href="16-01.html">Next</a>
</td>
</tr>
</table>
</center>
<hr width="90%" size="1" noshade="noshade" />
<div align="center">
Graphics Programming Black Book &copy; 2001 Michael Abrash
</div>
</body>
</html>