abrash-black-book/13-04.html
2013-12-30 12:21:49 +11:00

104 lines
7.7 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: Aiming the 486</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=13//-->
<!--PAGES=256-258//-->
<!--UNASSIGNED1//-->
<!--UNASSIGNED2//--></HEAD><BODY LINK=#0000FF ALINK=#000099 VLINK=#0000FF BGCOLOR=#FFFFFF>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="13-03.html">Previous</A></TD>
<TD><A HREF="index.html">Table of Contents</A></TD>
<TD><A HREF="14-01.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<P><BR></P>
<H3><A NAME="Heading7"></A><FONT COLOR="#000077">32-Bit Addressing Modes</FONT></H3>
<P>The 386 and 486 both support 32-bit addressing modes, in which any register may serve as the base memory addressing register, and almost any register may serve as the potentially scaled index register. For example,
</P>
<!-- CODE SNIP //-->
<PRE>
mov al,BaseTable[ecx&#43;edx*4]
</PRE>
<!-- END CODE SNIP //-->
<P>uses a perfectly valid 32-bit address, with the byte accessed being the one at the offset in DS pointed to by the sum of EDX times 4 plus the offset of <B>BaseTable</B> plus ECX. This is a very powerful memory addressing scheme, far superior to 8088-style 16-bit addressing, but it&#146;s not without its quirks and costs, so let&#146;s take a quick look at 32-bit addressing. (By the way, 32-bit addressing is not limited to protected mode; 32-bit instructions may be used in real mode, although each instruction that uses 32-bit addressing must have an address-size prefix byte, and the presence of a prefix byte costs a cycle on a 486.)</P>
<P>Any register may serve as the base register component of an address. Any register except ESP may also serve as the index register, which can be scaled by 1, 2, 4, or 8. (Scaling is very handy for performing lookups in arrays and tables.) The same register may serve as both base and index register, except for ESP, which can only be the base. Incidentally, it makes sense that ESP can&#146;t be scaled; ESP presumably always points to a valid stack, and I can&#146;t think of any reason you&#146;d want to use the stack pointer times 2, 4, or 8 in an address. ESP is, by its nature, a base rather than index pointer.</P>
<P>That&#146;s all there is to the functionality of 32-bit addressing; it&#146;s very simple, much simpler than 16-bit addressing, with its sharply limited memory addressing register combinations. The costs of 32-bit addressing are a bit more subtle. The only performance cost (apart from the aforementioned 1-cycle penalty for using 32-bit addressing in real mode) is a 1-cycle penalty imposed for using an index register. In this context, you use an index register when you use a register that&#146;s scaled, or when you use the sum of two registers to point to memory. <B>MOV BL,[EBX*2]</B> uses an index register and takes an extra cycle, as does <B>MOV CL,[EAX&#43;EDX]; MOV CL,[EAX&#43;100H]</B> is not indexed, however.</P>
<P>The other cost of 32-bit addressing is in instruction size. Old-style 16-bit addressing usually (except in a few special cases) uses one extra byte, which Intel calls the Mod-R/M byte, which is placed immediately after each instruction&#146;s opcode to describe the memory addressing mode, plus 1 or 2 optional bytes of addressing displacement&#151;that is, a constant value to add into the address. In many cases, 32-bit addressing continues to use the Mod-R/M byte, albeit with a different interpretation; in these cases, 32-bit addressing is no larger than 16-bit addressing, except when a 32-bit displacement is involved. For example, <B>MOV AL, [EBX]</B> is a 2-byte instruction; <B>MOV AL, [EBX&#43;10H]</B> is a 3-byte instruction; and <B>MOV AL, [EBX&#43;10000H]</B> is a 6-byte instruction.</P>
<TABLE WIDTH="100%"><TD ALIGN="LEFT" VALIGN="TOP" WIDTH="5%"><IMG SRC="images/13-03i.jpg"><TD ALIGN="LEFT" VALIGN="TOP" WIDTH="95%"><SMALL><I>Note that 1 and 4-byte displacements, but not 2-byte displacements, are supported for 32-bit addressing. Code size can be greatly improved by keeping stack frame variables within 128 bytes of EBP, and variables in pointed-to structures within 127 bytes of the start of the structure, so that displacements can be 1 rather than 4 bytes.</I></SMALL>
</TABLE>
<P>However, because 32-bit addressing supports many more addressing combinations than 16-bit addressing, the Mod-R/M byte can&#146;t describe all the combinations. Therefore, whenever an index register (as described above) is involved, a second byte, the SIB byte, follows the Mod-R/M byte to provide additional address information. Consequently, whenever you use a scaled memory addressing register or use the sum of two registers to point to memory, you automatically add 1 cycle and 1 byte to that instruction. This is not to say that you shouldn&#146;t use index registers when they&#146;re needed, but if you find yourself using them inside key loops, you should see if it&#146;s possible to move the index calculation outside the loop as, for example, in a loop like this:
</P>
<!-- CODE SNIP //-->
<PRE>
LoopTop:
add ax,DataTable[ebx*2]
inc ebx
dec cx
jnz LoopTop
</PRE>
<!-- END CODE SNIP //-->
<P>You could change this to the following for greater performance:
</P>
<!-- CODE SNIP //-->
<PRE>
add ebx,ebx ;ebx*2
LoopTop:
add ax,DataTable[ebx]
add ebxX,2
dec cx
jnz LoopTop
shr ebx,1 ;ebx*2/2
</PRE>
<!-- END CODE SNIP //-->
<P>I&#146;ll end this chapter with two more quirks of 32-bit addressing. First, as with 16-bit addressing, addressing that uses EBP as a base register both accesses the SS segment by default and always has a displacement of at least 1 byte. This reflects the common use of EBP to address a stack frame, but is worth keeping in mind if you should happen to use EBP to address non-stack memory.
</P>
<P>Lastly, as I mentioned, ESP cannot be scaled. In fact, ESP cannot be an index register; it must be a base register. Ironically, however, ESP is the one register that cannot be used to address memory without the presence of an SIB byte, even if it&#146;s used without an index register. This is an outcome of the way in which the SIB byte extends the capabilities of the Mod-R/M byte, and there&#146;s nothing to be done about it, but it&#146;s at least worth noting that ESP-based, non-indexed addressing makes for instructions that are a byte larger than other non-indexed addressing (but not any slower; there&#146;s no 1-cycle penalty for using ESP as a base register) on the 486.</P><P><BR></P>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="13-03.html">Previous</A></TD>
<TD><A HREF="index.html">Table of Contents</A></TD>
<TD><A HREF="14-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 &copy; 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 -->