Initial conversion to markdown
This commit is contained in:
parent
a96a114403
commit
5e10794a24
362 changed files with 67353 additions and 0 deletions
114
13-04.md
Normal file
114
13-04.md
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](13-03.html) [Table of Contents](index.html) [Next](14-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
### 32-Bit Addressing Modes {#Heading7}
|
||||
|
||||
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,
|
||||
|
||||
mov al,BaseTable[ecx+edx*4]
|
||||
|
||||
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 **BaseTable** plus ECX. This is a very powerful memory
|
||||
addressing scheme, far superior to 8088-style 16-bit addressing, but
|
||||
it’s not without its quirks and costs, so let’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.)
|
||||
|
||||
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’t be scaled; ESP presumably
|
||||
always points to a valid stack, and I can’t think of any reason you’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.
|
||||
|
||||
That’s all there is to the functionality of 32-bit addressing; it’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’s
|
||||
scaled, or when you use the sum of two registers to point to memory.
|
||||
**MOV BL,[EBX\*2]** uses an index register and takes an extra cycle, as
|
||||
does **MOV CL,[EAX+EDX]; MOV CL,[EAX+100H]** is not indexed, however.
|
||||
|
||||
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’s opcode to describe the memory addressing mode,
|
||||
plus 1 or 2 optional bytes of addressing displacement—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, **MOV AL, [EBX]** is a 2-byte instruction; **MOV AL,
|
||||
[EBX+10H]** is a 3-byte instruction; and **MOV AL, [EBX+10000H]** is a
|
||||
6-byte instruction.
|
||||
|
||||
------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
 *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.*
|
||||
------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
However, because 32-bit addressing supports many more addressing
|
||||
combinations than 16-bit addressing, the Mod-R/M byte can’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’t use index
|
||||
registers when they’re needed, but if you find yourself using them
|
||||
inside key loops, you should see if it’s possible to move the index
|
||||
calculation outside the loop as, for example, in a loop like this:
|
||||
|
||||
LoopTop:
|
||||
add ax,DataTable[ebx*2]
|
||||
inc ebx
|
||||
dec cx
|
||||
jnz LoopTop
|
||||
|
||||
You could change this to the following for greater performance:
|
||||
|
||||
add ebx,ebx ;ebx*2
|
||||
LoopTop:
|
||||
add ax,DataTable[ebx]
|
||||
add ebxX,2
|
||||
dec cx
|
||||
jnz LoopTop
|
||||
shr ebx,1 ;ebx*2/2
|
||||
|
||||
I’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.
|
||||
|
||||
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’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’s nothing to be done about
|
||||
it, but it’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’s no 1-cycle penalty
|
||||
for using ESP as a base register) on the 486.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](13-03.html) [Table of Contents](index.html) [Next](14-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
Loading…
Reference in a new issue