Replace invalid characters with HTML entities

— with —
’ with ’
+ with +
× with x
ç with ç
“ with “
” with ”
‘ with ‘
• with •
– with -
µ with µ
† with †
Fix C++
θ with θ
Yen symbol instead of times
Fix broken apos
Bullet again
E-circumflex
This commit is contained in:
James Gregory 2013-12-30 12:50:32 +11:00
commit 500e7f5654
353 changed files with 5091 additions and 5091 deletions

View file

@ -40,7 +40,7 @@
<!-- CODE //-->
<PRE>
ClearS proc near
push bp ;save caller&#146;s BP
push bp ;save caller&rsquo;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
@ -53,42 +53,42 @@ Start: cld ;make STOSW count up
mov cx,[bp].BufSize ;load CX with buffer size
rep stosw ;fill the buffer
Bye:
pop bp ;restore caller&#146;s BP
pop bp ;restore caller&rsquo;s BP
ret EndMrk-RetAddr-2 ;return, clearing the parms from the stack
ClearS endp
</PRE>
<!-- END CODE //-->
<P>(We could get rid of yet another instruction by having the calling code pack both the attribute and the fill value into the same word, but that&#146;s not part of the specification for this particular routine.)
<P>(We could get rid of yet another instruction by having the calling code pack both the attribute and the fill value into the same word, but that&rsquo;s not part of the specification for this particular routine.)
</P>
<P>Another nifty instruction-rearrangement trick saves 6 more bytes. <B>ClearS</B> checks to see whether the far pointer is null (zero) at the start of the routine...then loads and uses that same far pointer later on. Let&#146;s get that pointer into registers and keep it there; that way we can check to see whether it&#146;s null with a single comparison, and can use it later without having to reload it from memory. This technique is shown in Listing 22.6.</P>
<P>Another nifty instruction-rearrangement trick saves 6 more bytes. <B>ClearS</B> checks to see whether the far pointer is null (zero) at the start of the routine...then loads and uses that same far pointer later on. Let&rsquo;s get that pointer into registers and keep it there; that way we can check to see whether it&rsquo;s null with a single comparison, and can use it later without having to reload it from memory. This technique is shown in Listing 22.6.</P>
<P><B>LISTING 22.6 L22-6.ASM</B></P>
<!-- CODE //-->
<PRE>
ClearS proc near
push bp ;save caller&#146;s BP
push bp ;save caller&rsquo;s BP
mov bp,sp ;point to stack frame
les di,dword ptr [bp].BufOfs ;load ES:DI with target buffer;segment:offset
mov ax,es ;put segment where we can test it
or ax,di ;is it a null pointer?
je Bye ;yes, so we&#146;re done
je Bye ;yes, so we&rsquo;re done
Start: cld ;make STOSW count up
mov ah,byte ptr [bp].Attrib[1];load AH with attribute
mov al,byte ptr [bp].Filler ;load AL with fill char
mov cx,[bp].BufSize ;load CX with buffer size
rep stosw ;fill the buffer
Bye:
pop bp ;restore caller&#146;s BP
pop bp ;restore caller&rsquo;s BP
ret EndMrk-RetAddr-2 ;return, clearing the parms from the stack
ClearS endp
</PRE>
<!-- END CODE //-->
<P>Well. Now we&#146;re down to 28 bytes, having reduced the size of this subroutine by nearly 50 percent. Only 13 instructions remain. Realistically, how much smaller can we make this code?
<P>Well. Now we&rsquo;re down to 28 bytes, having reduced the size of this subroutine by nearly 50 percent. Only 13 instructions remain. Realistically, how much smaller can we make this code?
</P>
<P>About one-third smaller yet, as it turns out&#151;but in order to do that, we must stretch our minds and use the 8088&#146;s instructions in unusual ways. Let me ask you this: What do most of the instructions in the current version of <B>ClearS</B> do?</P>
<P>They either load parameters from the stack frame or set up the registers so that the parameters can be accessed. Mind you, there&#146;s nothing wrong with the stack-frame-oriented instructions used in <B>ClearS</B>; those instructions access the stack frame in a highly efficient way, exactly as the designers of the 8088 intended, and just as the code generated by a high-level language would. That means that we aren&#146;t going to be able to improve the code if we don&#146;t bend the rules a bit.</P>
<P>Let&#146;s think...the parameters are sitting on the stack, and most of our instruction bytes are being used to read bytes off the stack with BP-based addressing...we need a more efficient way to address the stack...<I>the stack</I>...THE STACK!</P>
<P>Ye gods! That&#146;s easy&#151;we can use the <I>stack pointer</I> to address the stack rather than BP. While it&#146;s true that the stack pointer can&#146;t be used for <I>mod-reg-rm</I> addressing, as BP can, it <I>can</I> be used to pop data off the stack&#151;and <B>POP</B> is a one-byte instruction. Instructions don&#146;t get any shorter than that.</P>
<P>There is one detail to be taken care of before we can put our plan into action: The return address&#151;the address of the calling code&#151;is on top of the stack, so the parameters we want can&#146;t be reached with <B>POP</B>. That&#146;s easily solved, however&#151;we&#146;ll just pop the return address into an unused register, then branch through that register when we&#146;re done, as we learned to do in Chapter 14. As we pop the parameters, we&#146;ll also be removing them from the stack, thereby neatly avoiding the need to discard them when it&#146;s time to return.</P>
<P>About one-third smaller yet, as it turns out&mdash;but in order to do that, we must stretch our minds and use the 8088&rsquo;s instructions in unusual ways. Let me ask you this: What do most of the instructions in the current version of <B>ClearS</B> do?</P>
<P>They either load parameters from the stack frame or set up the registers so that the parameters can be accessed. Mind you, there&rsquo;s nothing wrong with the stack-frame-oriented instructions used in <B>ClearS</B>; those instructions access the stack frame in a highly efficient way, exactly as the designers of the 8088 intended, and just as the code generated by a high-level language would. That means that we aren&rsquo;t going to be able to improve the code if we don&rsquo;t bend the rules a bit.</P>
<P>Let&rsquo;s think...the parameters are sitting on the stack, and most of our instruction bytes are being used to read bytes off the stack with BP-based addressing...we need a more efficient way to address the stack...<I>the stack</I>...THE STACK!</P>
<P>Ye gods! That&rsquo;s easy&mdash;we can use the <I>stack pointer</I> to address the stack rather than BP. While it&rsquo;s true that the stack pointer can&rsquo;t be used for <I>mod-reg-rm</I> addressing, as BP can, it <I>can</I> be used to pop data off the stack&mdash;and <B>POP</B> is a one-byte instruction. Instructions don&rsquo;t get any shorter than that.</P>
<P>There is one detail to be taken care of before we can put our plan into action: The return address&mdash;the address of the calling code&mdash;is on top of the stack, so the parameters we want can&rsquo;t be reached with <B>POP</B>. That&rsquo;s easily solved, however&mdash;we&rsquo;ll just pop the return address into an unused register, then branch through that register when we&rsquo;re done, as we learned to do in Chapter 14. As we pop the parameters, we&rsquo;ll also be removing them from the stack, thereby neatly avoiding the need to discard them when it&rsquo;s time to return.</P>
<P>With that problem dealt with, Listing 22.7 shows the Zenned version of <B>ClearS</B>.</P>
<P><B>LISTING 22.7 L22-7.ASM</B></P>
<!-- CODE //-->
@ -103,7 +103,7 @@ ClearS procnear
pop es ;get the segment of the buffer origin
mov bx,es ;put the segment where we can test it
or bx,di ;null pointer?
je Bye ;yes, so we&#146;re done
je Bye ;yes, so we&rsquo;re done
cld ;make STOSW count up
rep stosw ;do the string store
Bye:
@ -111,8 +111,8 @@ Bye:
ClearS endp
</PRE>
<!-- END CODE //-->
<P>At long last, we&#146;re down to the bare metal. This version of <B>ClearS</B> is just 19 bytes long. That&#146;s just 37 percent as long as the original version, <I>without any change whatsoever in the functionality that <B>ClearS</B> makes available to the calling code</I>. The code is bound to run a bit faster too, given that there are far fewer instruction bytes and fewer memory accesses.</P>
<P>All in all, the Zenned version of <B>ClearS</B> is a vast improvement over the original. Probably not the best possible implementation&#151;<I>never say never!</I>&#151;but an awfully good one.</P><P><BR></P>
<P>At long last, we&rsquo;re down to the bare metal. This version of <B>ClearS</B> is just 19 bytes long. That&rsquo;s just 37 percent as long as the original version, <I>without any change whatsoever in the functionality that <B>ClearS</B> makes available to the calling code</I>. The code is bound to run a bit faster too, given that there are far fewer instruction bytes and fewer memory accesses.</P>
<P>All in all, the Zenned version of <B>ClearS</B> is a vast improvement over the original. Probably not the best possible implementation&mdash;<I>never say never!</I>&mdash;but an awfully good one.</P><P><BR></P>
<CENTER>
<TABLE BORDER>
<TR>