Use backtick code blocks for syntax highlighting
This commit is contained in:
parent
8ed9dea394
commit
f658bfbb40
203 changed files with 26546 additions and 25801 deletions
108
21-02.md
108
21-02.md
|
|
@ -15,16 +15,22 @@ stack pointer. Implicit modifiers of ESP, such as **PUSH** and **POP**,
|
|||
are special-cased so you don't have to worry about AGIs. However, if you
|
||||
explicitly modify ESP with this instruction
|
||||
|
||||
sub esp,100h
|
||||
```nasm
|
||||
sub esp,100h
|
||||
```
|
||||
|
||||
for example, or with the popular
|
||||
|
||||
mov esp,ebp
|
||||
```nasm
|
||||
mov esp,ebp
|
||||
```
|
||||
|
||||
you can then get AGIs if you attempt to use ESP to address memory,
|
||||
either explicitly with instructions like this one
|
||||
|
||||
moveax,[esp+20h]
|
||||
```nasm
|
||||
moveax,[esp+20h]
|
||||
```
|
||||
|
||||
or via **PUSH**, **POP**, or other instructions that implicitly use ESP
|
||||
as an addressing register.
|
||||
|
|
@ -32,25 +38,31 @@ as an addressing register.
|
|||
On the 486, any instruction that had both a constant value and an
|
||||
addressing displacement, such as
|
||||
|
||||
mov dword ptr [ebp+16],1
|
||||
```nasm
|
||||
mov dword ptr [ebp+16],1
|
||||
```
|
||||
|
||||
suffered a 1-cycle penalty, taking a total of 2 cycles. Such
|
||||
instructions take only one cycle on the Pentium, but they cannot pair,
|
||||
so they're still the most expensive sort of **MOV**. Knowing this can
|
||||
speed up something as simple as zeroing two memory variables, as in
|
||||
|
||||
sub eax,eax ;U-pipe 1
|
||||
;any V-pipe pairable
|
||||
; instruction can go here,
|
||||
; or SUB could be in V-pipe
|
||||
mov [MemVar1],eax ;U-pipe 2
|
||||
mov [MemVar2],eax ;V-pipe 2
|
||||
```nasm
|
||||
sub eax,eax ;U-pipe 1
|
||||
;any V-pipe pairable
|
||||
; instruction can go here,
|
||||
; or SUB could be in V-pipe
|
||||
mov [MemVar1],eax ;U-pipe 2
|
||||
mov [MemVar2],eax ;V-pipe 2
|
||||
```
|
||||
|
||||
which should never be slower and should potentially be 0.5 cycles
|
||||
faster, and six bytes smaller than this sequence:
|
||||
|
||||
mov [MemVar1],0 ;U-pipe 1
|
||||
mov [MemVar2],0 ;U-pipe 2
|
||||
```nasm
|
||||
mov [MemVar1],0 ;U-pipe 1
|
||||
mov [MemVar2],0 ;U-pipe 2
|
||||
```
|
||||
|
||||
Note, however, that my experiments thus far indicate that the two writes
|
||||
in the first case don't actually pair (possibly because the memory
|
||||
|
|
@ -66,10 +78,12 @@ optimization: register contention. The basic premise here is simple: You
|
|||
can't use the same register in two inherently sequential ways in a
|
||||
single cycle. For example, you can't execute
|
||||
|
||||
inc eax ;U-pipe cycle 1
|
||||
;V-pipe idle cycle 1
|
||||
; due to dependency
|
||||
and ebx,eax ;U-pipe cycle 2
|
||||
```nasm
|
||||
inc eax ;U-pipe cycle 1
|
||||
;V-pipe idle cycle 1
|
||||
; due to dependency
|
||||
and ebx,eax ;U-pipe cycle 2
|
||||
```
|
||||
|
||||
in a single cycle; **AND EBX,EAX** can't execute until the value in EAX
|
||||
is known, and that can't happen until **INC EAX** is done. Consequently,
|
||||
|
|
@ -86,10 +100,12 @@ to write to the same register on the same cycle. While that may not seem
|
|||
like a particularly useful operation in general, it can happen when
|
||||
subregisters are being set, as in the following
|
||||
|
||||
sub eax,eax ;U-pipe cycle 1
|
||||
;V-pipe idle cycle 1
|
||||
; due to register contention
|
||||
mov al,[Var] ;U-pipe cycle 2
|
||||
```nasm
|
||||
sub eax,eax ;U-pipe cycle 1
|
||||
;V-pipe idle cycle 1
|
||||
; due to register contention
|
||||
mov al,[Var] ;U-pipe cycle 2
|
||||
```
|
||||
|
||||
where an attempt is made to set both EAX and its AL subregister on the
|
||||
same cycle. Write-after-write contention implies that the two
|
||||
|
|
@ -103,8 +119,10 @@ Intel has special-cased some very useful exceptions to register
|
|||
contention. Happily, write-after-read operations do *not* cause
|
||||
contention. Such operations, as in
|
||||
|
||||
mov eax,edx ;U-pipe cycle 1
|
||||
sub edx,edxX ;V-pipe cycle 1
|
||||
```nasm
|
||||
mov eax,edx ;U-pipe cycle 1
|
||||
sub edx,edxX ;V-pipe cycle 1
|
||||
```
|
||||
|
||||
are free of charge.
|
||||
|
||||
|
|
@ -117,12 +135,14 @@ register contention on ESP—but not AGIs—with instructions that use ESP
|
|||
explicitly, such as **MOV EAX,[ESP+4]**.) Without this special case, the
|
||||
following sequence would hardly use the V-pipe at all:
|
||||
|
||||
mov eax,[MemVar] ;U-pipe cycle 1
|
||||
push esi ;V-pipe cycle 1
|
||||
push eax ;U-pipe cycle 2
|
||||
push edi ;V-pipe cycle 2
|
||||
push ebx ;U-pipe cycle 3
|
||||
call FooTilde ;V-pipe cycle 3
|
||||
```nasm
|
||||
mov eax,[MemVar] ;U-pipe cycle 1
|
||||
push esi ;V-pipe cycle 1
|
||||
push eax ;U-pipe cycle 2
|
||||
push edi ;V-pipe cycle 2
|
||||
push ebx ;U-pipe cycle 3
|
||||
call FooTilde ;V-pipe cycle 3
|
||||
```
|
||||
|
||||
But in fact, all the instructions pair, even though ESP is modified five
|
||||
times in the space of six instructions.
|
||||
|
|
@ -133,11 +153,13 @@ pair only in the V-pipe: branches. Any near call or conditional or
|
|||
unconditional near jump can execute in the V-pipe paired with any
|
||||
pairable U-pipe instruction, as illustrated by this sequence:
|
||||
|
||||
LoopTop:
|
||||
mov [esi],eax ;U-pipe cycle 1
|
||||
add esi,4 ;V-pipe cycle 1
|
||||
dec ecx ;U-pipe cycle 2
|
||||
jnz LoopTop ;V-pipe cycle 2
|
||||
```nasm
|
||||
LoopTop:
|
||||
mov [esi],eax ;U-pipe cycle 1
|
||||
add esi,4 ;V-pipe cycle 1
|
||||
dec ecx ;U-pipe cycle 2
|
||||
jnz LoopTop ;V-pipe cycle 2
|
||||
```
|
||||
|
||||
Branches can't pair in the U-pipe; a branch that executes in the U-pipe
|
||||
runs alone, with the V-pipe idle. If a call or jump is correctly
|
||||
|
|
@ -159,12 +181,14 @@ instruction, the other instructions will go through different pipes than
|
|||
previously, and cause the loop as a whole to take 50 percent longer,
|
||||
even though we only added 25 percent more cycles:
|
||||
|
||||
LoopTop:
|
||||
inc edx ;U-pipe cycle 1
|
||||
mov [esi],eax ;V-pipe cycle 1
|
||||
add esi,4 ;U-pipe cycle 2
|
||||
dec ecx ;V-pipe cycle 2
|
||||
jnz LoopTop ;U-pipe cycle 3
|
||||
;V-pipe idle cycle 3
|
||||
; because JNZ can't
|
||||
; pair in the U-pipe
|
||||
```nasm
|
||||
LoopTop:
|
||||
inc edx ;U-pipe cycle 1
|
||||
mov [esi],eax ;V-pipe cycle 1
|
||||
add esi,4 ;U-pipe cycle 2
|
||||
dec ecx ;V-pipe cycle 2
|
||||
jnz LoopTop ;U-pipe cycle 3
|
||||
;V-pipe idle cycle 3
|
||||
; because JNZ can't
|
||||
; pair in the U-pipe
|
||||
```
|
||||
|
|
|
|||
Loading…
Reference in a new issue