Normal quotes
This commit is contained in:
parent
5e10794a24
commit
18011c595a
352 changed files with 6040 additions and 6040 deletions
32
11-08.md
32
11-08.md
|
|
@ -2,10 +2,10 @@
|
|||
[Previous](11-07.html) [Table of Contents](index.html) [Next](12-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Well, there’s only one instruction other than **POPF** that loads the
|
||||
FLAGS register directly from the stack, and that’s **IRET**, which loads
|
||||
Well, there's only one instruction other than **POPF** that loads the
|
||||
FLAGS register directly from the stack, and that's **IRET**, which loads
|
||||
the FLAGS register from the stack as it branches, as shown in Figure
|
||||
11.5. iret has no known bugs of the sort that plague **POPF**, so it’s
|
||||
11.5. iret has no known bugs of the sort that plague **POPF**, so it's
|
||||
certainly a candidate to replace popf in non-interruptible applications.
|
||||
Unfortunately, **IRET** loads the FLAGS register with the *third* word
|
||||
down on the stack, not the word on top of the stack, as is the case with
|
||||
|
|
@ -14,13 +14,13 @@ between the top of the stack and the word popped into the FLAGS
|
|||
register.
|
||||
|
||||
Obviously, the segment:offset that **IRET** expects to find on the stack
|
||||
above the pushed flags isn’t present when the stack is set up for
|
||||
**POPF**, so we’ll have to adjust the stack a bit before we can
|
||||
substitute **IRET** for **POPF**. What we’ll have to do is push the
|
||||
above the pushed flags isn't present when the stack is set up for
|
||||
**POPF**, so we'll have to adjust the stack a bit before we can
|
||||
substitute **IRET** for **POPF**. What we'll have to do is push the
|
||||
segment:offset of the instruction after our workaround code onto the
|
||||
stack right above the pushed flags. **IRET** will then branch to that
|
||||
address and pop the flags, ending up at the instruction after the
|
||||
workaround code with the flags popped. That’s just the result that would
|
||||
workaround code with the flags popped. That's just the result that would
|
||||
have occurred had we executed **POPF**—WITH the bonus that no interrupts
|
||||
can accidentally occur when the Interrupt flag is 0 both before and
|
||||
after the pop.
|
||||
|
|
@ -32,7 +32,7 @@ How can we push the segment:offset of the next instruction? Well,
|
|||
finding the offset of the next instruction by performing a near call to
|
||||
that instruction is a tried-and-true trick. We can do something similar
|
||||
here, but in this case we need a far call, since **IRET** requires both
|
||||
a segment and an offset. We’ll also branch backward so that the address
|
||||
a segment and an offset. We'll also branch backward so that the address
|
||||
pushed on the stack will point to the instruction we want to continue
|
||||
with. The code works out like this:
|
||||
|
||||
|
|
@ -72,7 +72,7 @@ shrinking the workaround code by 1 byte:
|
|||
call popfiret
|
||||
endm
|
||||
|
||||
By the way, the flags can be popped much more quickly if you’re willing
|
||||
By the way, the flags can be popped much more quickly if you're willing
|
||||
to alter a register in the process. For example, the following macro
|
||||
emulates **POPF** with just one branch, but wipes out AX:
|
||||
|
||||
|
|
@ -83,11 +83,11 @@ emulates **POPF** with just one branch, but wipes out AX:
|
|||
iret
|
||||
endm
|
||||
|
||||
It’s not a perfect substitute for **POPF**, since **POPF** doesn’t alter
|
||||
any registers, but it’s faster and shorter than **EMULATE\_POPF** when
|
||||
you can spare the register. If you’re using 286-specific instructions,
|
||||
It's not a perfect substitute for **POPF**, since **POPF** doesn't alter
|
||||
any registers, but it's faster and shorter than **EMULATE\_POPF** when
|
||||
you can spare the register. If you're using 286-specific instructions,
|
||||
you can use which is shorter still, alters no registers, and branches
|
||||
just once. (Of course, this version of **EMULATE\_POPF** won’t work on
|
||||
just once. (Of course, this version of **EMULATE\_POPF** won't work on
|
||||
an 8088.)
|
||||
|
||||
.286
|
||||
|
|
@ -102,16 +102,16 @@ an 8088.)
|
|||
**Figure 11.6** *Workaround code for the POPF bug.*
|
||||
|
||||
The standard version of **EMULATE\_POPF** is 6 bytes longer than
|
||||
**POPF** and much slower, as you’d expect given that it involves three
|
||||
**POPF** and much slower, as you'd expect given that it involves three
|
||||
branches. Anyone in his/her right mind would prefer **POPF** to a
|
||||
larger, slower, three-branch macro—given a choice. In noncode, however,
|
||||
there’s no choice here; the safer—if slower—approach is the best.
|
||||
there's no choice here; the safer—if slower—approach is the best.
|
||||
(Having people associate your programs with crashed computers is *not* a
|
||||
desirable situation, no matter how unfair the circumstances under which
|
||||
it occurs.)
|
||||
|
||||
And now you know the nature of and the workaround for the **POPF** bug.
|
||||
Whether you ever need the workaround or not, it’s a neatly packaged
|
||||
Whether you ever need the workaround or not, it's a neatly packaged
|
||||
example of the tremendous flexibility of the x86 instruction set.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
|
|
|||
Loading…
Reference in a new issue