Use backtick code blocks for syntax highlighting

This commit is contained in:
James Gregory 2013-12-31 11:38:48 +11:00
commit f658bfbb40
203 changed files with 26546 additions and 25801 deletions

108
21-02.md
View file

@ -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
```