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
98
07-05.md
98
07-05.md
|
|
@ -19,9 +19,11 @@ simple task of setting bit N of AX to 1.
|
|||
The obvious way to do this is to place N in CL, rotate the bit into
|
||||
position, and OR it with AX, as follows:
|
||||
|
||||
MOV BX,1
|
||||
SHL BX,CL
|
||||
OR AX,BX
|
||||
```nasm
|
||||
MOV BX,1
|
||||
SHL BX,CL
|
||||
OR AX,BX
|
||||
```
|
||||
|
||||
This solution is obvious because it takes good advantage of the special
|
||||
ability of the x86 family to shift or rotate by the variable number of
|
||||
|
|
@ -31,15 +33,17 @@ bit number in BX, and look the shifted bit up, as shown in Listing 7.3.
|
|||
|
||||
**LISTING 7.3 L7-3.ASM**
|
||||
|
||||
SHL BX,1 ;prepare for word sized look up
|
||||
OR AX,ShiftTable[BX] ;look up the bit and OR it in
|
||||
:
|
||||
ShiftTable LABEL WORD
|
||||
BIT_PATTERN=0001H
|
||||
REPT 16
|
||||
DW BIT_PATTERN
|
||||
BIT_PATTERN=BIT_PATTERN SHL 1
|
||||
ENDM
|
||||
```nasm
|
||||
SHL BX,1 ;prepare for word sized look up
|
||||
OR AX,ShiftTable[BX] ;look up the bit and OR it in
|
||||
:
|
||||
ShiftTable LABEL WORD
|
||||
BIT_PATTERN=0001H
|
||||
REPT 16
|
||||
DW BIT_PATTERN
|
||||
BIT_PATTERN=BIT_PATTERN SHL 1
|
||||
ENDM
|
||||
```
|
||||
|
||||
Even though it accesses memory, this approach takes only 20 cycles—more
|
||||
than twice as fast as the variable shift. Once again, we were able to
|
||||
|
|
@ -55,14 +59,16 @@ code snippet in Listing 7.4.
|
|||
|
||||
**LISTING 7.4 L7-4.ASM**
|
||||
|
||||
OR EAX,ShiftTable[EBX*4] ;look up the bit and OR it in
|
||||
:
|
||||
ShiftTable LABEL DWORD
|
||||
BIT_PATTERN=0001H
|
||||
REPT 32
|
||||
DD BIT_PATTERN
|
||||
BIT_PATTERN=BIT_PATTERN SHL 1
|
||||
ENDM
|
||||
```nasm
|
||||
OR EAX,ShiftTable[EBX*4] ;look up the bit and OR it in
|
||||
:
|
||||
ShiftTable LABEL DWORD
|
||||
BIT_PATTERN=0001H
|
||||
REPT 32
|
||||
DD BIT_PATTERN
|
||||
BIT_PATTERN=BIT_PATTERN SHL 1
|
||||
ENDM
|
||||
```
|
||||
|
||||
> 
|
||||
> Besides illustrating the advantages of local optimization, this example
|
||||
|
|
@ -119,30 +125,34 @@ addition to the next.
|
|||
|
||||
**LISTING 7.5 L7-5.ASM**
|
||||
|
||||
CLC ;clear the Carry for the initial addition
|
||||
LOOP_TOP:
|
||||
MOV AX,[SI];get next source operand word
|
||||
ADC [DI],AX;add with Carry to dest operand word
|
||||
INC SI ;point to next source operand word
|
||||
INC SI
|
||||
INC DI ;point to next dest operand word
|
||||
INC DI
|
||||
LOOP LOOP_TOP
|
||||
```nasm
|
||||
CLC ;clear the Carry for the initial addition
|
||||
LOOP_TOP:
|
||||
MOV AX,[SI];get next source operand word
|
||||
ADC [DI],AX;add with Carry to dest operand word
|
||||
INC SI ;point to next source operand word
|
||||
INC SI
|
||||
INC DI ;point to next dest operand word
|
||||
INC DI
|
||||
LOOP LOOP_TOP
|
||||
```
|
||||
|
||||
If **ADD** were used, the Carry flag would have to be saved between
|
||||
additions, with code along the lines shown in Listing 7.6.
|
||||
|
||||
**LISTING 7.6 L7-6.ASM**
|
||||
|
||||
CLC ;clear the carry for the initial addition
|
||||
LOOP_TOP:
|
||||
MOV AX,[SI] ;get next source operand word
|
||||
ADC [DI],AX ;add with carry to dest operand word
|
||||
LAHF ;set aside the carry flag
|
||||
ADD SI,2 ;point to next source operand word
|
||||
ADD DI,2 ;point to next dest operand word
|
||||
SAHF ;restore the carry flag
|
||||
LOOP LOOP_TOP
|
||||
```nasm
|
||||
CLC ;clear the carry for the initial addition
|
||||
LOOP_TOP:
|
||||
MOV AX,[SI] ;get next source operand word
|
||||
ADC [DI],AX ;add with carry to dest operand word
|
||||
LAHF ;set aside the carry flag
|
||||
ADD SI,2 ;point to next source operand word
|
||||
ADD DI,2 ;point to next dest operand word
|
||||
SAHF ;restore the carry flag
|
||||
LOOP LOOP_TOP
|
||||
```
|
||||
|
||||
It's not that the Listing 7.6 approach is necessarily better or worse;
|
||||
that depends on the processor and the situation. The Listing 7.6
|
||||
|
|
@ -182,13 +192,17 @@ an 8088 but are relatively slow instructions on the 486 and Pentium.
|
|||
There are times when it's a clear liability that **INC** doesn't set the
|
||||
Carry flag. For instance
|
||||
|
||||
INC AX
|
||||
ADC DX,0
|
||||
```nasm
|
||||
INC AX
|
||||
ADC DX,0
|
||||
```
|
||||
|
||||
does *not* increment the 32-bit value in DX:AX. To do that, you'd need
|
||||
the following:
|
||||
|
||||
ADD AX,1
|
||||
ADC DX,0
|
||||
```nasm
|
||||
ADD AX,1
|
||||
ADC DX,0
|
||||
```
|
||||
|
||||
As always, pay attention!
|
||||
Loading…
Reference in a new issue