Change bold code snippets to inline code blocks
This commit is contained in:
parent
f658bfbb40
commit
3c76d884ef
185 changed files with 1772 additions and 1772 deletions
34
12-03.md
34
12-03.md
|
|
@ -26,14 +26,14 @@ Rule \#2A: Rule \#2 sometimes, but not always, applies to the stack
|
|||
pointer when it is implicitly used to point to memory.
|
||||
|
||||
Intel states that the stack pointer is an implied destination register
|
||||
for **CALL**, **ENTER**, **LEAVE**, **RET**, **PUSH**, and **POP**
|
||||
for `CALL`, `ENTER`, `LEAVE`, `RET`, `PUSH`, and `POP`
|
||||
(which alter (E)SP), and that it is the implied base addressing register
|
||||
for **PUSH**, **POP**, and **RET** (which use (E)SP to address memory).
|
||||
for `PUSH`, `POP`, and `RET` (which use (E)SP to address memory).
|
||||
Intel then implies that the aforementioned addressing pipeline penalty
|
||||
is incurred whenever the stack pointer is used as a destination by one
|
||||
of the first set of instructions and is then immediately used to address
|
||||
memory by one of the second set. This raises the specter of unpleasant
|
||||
programming contortions such as intermixing **PUSH**es and **POP**s with
|
||||
programming contortions such as intermixing `PUSH`es and `POP`s with
|
||||
other instructions to avoid interrupting the addressing pipeline.
|
||||
Fortunately, matters are actually not so grim as Intel's documentation
|
||||
would indicate; my tests indicate that the addressing pipeline penalty
|
||||
|
|
@ -52,7 +52,7 @@ et
|
|||
|
||||
to exhibit the addressing pipeline interruption phenomenon (SP is both
|
||||
destination and addressing register for both instructions, according to
|
||||
Intel), but this code runs in six cycles per **POP/RET** pair, matching
|
||||
Intel), but this code runs in six cycles per `POP/RET` pair, matching
|
||||
the official execution times exactly. Likewise, a sequence like
|
||||
|
||||
```nasm
|
||||
|
|
@ -66,7 +66,7 @@ runs in one cycle per instruction, just as it should.
|
|||
|
||||
On the other hand, performing arithmetic directly on SP as an *explicit*
|
||||
destination—for example, to deallocate local variables—and then using
|
||||
**PUSH**, **POP**, or **RET**, definitely can interrupt the addressing
|
||||
`PUSH`, `POP`, or `RET`, definitely can interrupt the addressing
|
||||
pipeline. For example
|
||||
|
||||
```nasm
|
||||
|
|
@ -89,12 +89,12 @@ I certainly haven't tried all possible combinations, but the results so
|
|||
far indicate that the stack pointer incurs the addressing pipeline
|
||||
penalty only if (E)SP is the *explicit* destination of one instruction
|
||||
and is then used by one of the two following instructions to address
|
||||
memory. So, for instance, SP isn't the explicit operand of **POP AX—**AX
|
||||
is—and no cycles are lost if **POP AX** is followed by **POP** or
|
||||
**RET**. Happily, then, we need not worry about the sequence in which we
|
||||
use **PUSH** and **POP**. However, adding to, moving to, or subtracting
|
||||
memory. So, for instance, SP isn't the explicit operand of `POP AX`-AX
|
||||
is—and no cycles are lost if `POP AX` is followed by `POP` or
|
||||
`RET`. Happily, then, we need not worry about the sequence in which we
|
||||
use `PUSH` and `POP`. However, adding to, moving to, or subtracting
|
||||
from the stack pointer should ideally be done at least two cycles before
|
||||
**PUSH**, **POP**, **RET**, or any other instruction that uses the stack
|
||||
`PUSH`, `POP`, `RET`, or any other instruction that uses the stack
|
||||
pointer to address memory.
|
||||
|
||||
#### Problems with Byte Registers {#Heading9}
|
||||
|
|
@ -144,7 +144,7 @@ important that you understand why this rule exists (only that it *does*
|
|||
in fact exist), but it is an interesting window on the way the 486
|
||||
works.
|
||||
|
||||
In case you're curious, there's no such penalty for the typical **XLAT**
|
||||
In case you're curious, there's no such penalty for the typical `XLAT`
|
||||
sequence like
|
||||
|
||||
```nasm
|
||||
|
|
@ -154,20 +154,20 @@ mov al,[si]
|
|||
xlat
|
||||
```
|
||||
|
||||
even though AL must be converted to a word by **XLAT** before it can be
|
||||
even though AL must be converted to a word by `XLAT` before it can be
|
||||
added to BX and used to address memory. In fact, none of the penalties
|
||||
mentioned in this chapter apply to **XLAT**, apparently because **XLAT**
|
||||
mentioned in this chapter apply to `XLAT`, apparently because `XLAT`
|
||||
is so slow—4 cycles—that it gives the 486 time to perform addressing
|
||||
calculations during the course of the instruction.
|
||||
|
||||
> 
|
||||
> While it's nice that **XLAT** doesn't suffer from the various 486
|
||||
> addressing penalties, the reason for that is basically that **XLAT** is
|
||||
> slow, so there's still no compelling reason to use **XLAT** on the 486.
|
||||
> While it's nice that `XLAT` doesn't suffer from the various 486
|
||||
> addressing penalties, the reason for that is basically that `XLAT` is
|
||||
> slow, so there's still no compelling reason to use `XLAT` on the 486.
|
||||
|
||||
In general, penalties for interrupting the 486's pipeline apply
|
||||
primarily to the fast core instructions of the 486, most notably
|
||||
register-only instructions and **MOV**, although arithmetic and logical
|
||||
register-only instructions and `MOV`, although arithmetic and logical
|
||||
operations that access memory are also often affected. I don't know all
|
||||
the performance dependencies, and I don't plan to; figuring all of them
|
||||
out would be a big, boring job of little value. Basically, on the 486
|
||||
|
|
|
|||
Loading…
Reference in a new issue