diff --git a/src/chapter-21.md b/src/chapter-21.md old mode 100644 new mode 100755 index e6db869..523f050 --- a/src/chapter-21.md +++ b/src/chapter-21.md @@ -236,7 +236,7 @@ contention. Happily, write-after-read operations do *not* cause contention. Such operations, as in ```nasm -mov eax,edx ;U-pipe cycle 1 +mov eax,edx ;U-pipe cycle 1 sub edx,edxX ;V-pipe cycle 1 ``` @@ -475,33 +475,33 @@ ckloopsetup: mov dx,[esi] ;load most of 1st word to mov bl,[esi+2] ; checksum (last byte loaded in loop) dec ecx ;any more dwords to checksum? - jz short ckloopend ;no + jz short ckloopend ;no ckloop: - mov bh,[esi+3] ;cycle 1 U-pipe - add esi,4 ;cycle 1 V-pipe - shl ebx,16 ;cycle 2 U-pipe - ;cycle 2 V-pipe idle - ; (register contention) - or ebx,edx ;cycle 3 U-pipe - mov dl,[esi] ;cycle 3 V-pipe - add eax,ebx ;cycle 4 U-pipe - mov bl,[esi+2] ;cycle 4 V-pipe - adc eax,0 ;cycle 5 U-pipe - mov dh,[esi+1] ;cycle 5 V-pipe - dec ecx ;cycle 6 U-pipe - jnz ckloop ;cycle 6 V-pipe + mov bh,[esi+3] ;cycle 1 U-pipe + add esi,4 ;cycle 1 V-pipe + shl ebx,16 ;cycle 2 U-pipe + ;cycle 2 V-pipe idle + ; (register contention) + or ebx,edx ;cycle 3 U-pipe + mov dl,[esi] ;cycle 3 V-pipe + add eax,ebx ;cycle 4 U-pipe + mov bl,[esi+2] ;cycle 4 V-pipe + adc eax,0 ;cycle 5 U-pipe + mov dh,[esi+1] ;cycle 5 V-pipe + dec ecx ;cycle 6 U-pipe + jnz ckloop ;cycle 6 V-pipe ckloopend: - mov bh,[esi+3] ;checksum the last dword - add ax,dx - adc ax,bx - adc ax,0 + mov bh,[esi+3] ;checksum the last dword + add ax,dx + adc ax,bx + adc ax,0 - mov edx,eax ;compress the 32-bit checksum - shr edx,16 ; into a 16-bit checksum - add ax,dx - adc eax,0 + mov edx,eax ;compress the 32-bit checksum + shr edx,16 ; into a 16-bit checksum + add ax,dx + adc eax,0 ckloopdone: ``` @@ -598,29 +598,29 @@ more registers. jz short ckloopdone ;no, done add esi,4 ;point to the next dword noodddword: - mov edx,[esi] ;preload the first dword - mov ebx,[esi+4] ;preload the second dword - dec ecx ;we'll do 1 checksum outside the loop - jz short ckloopend ;only 1 checksum to do - add esi,8 ;point to the next dword + mov edx,[esi] ;preload the first dword + mov ebx,[esi+4] ;preload the second dword + dec ecx ;we'll do 1 checksum outside the loop + jz short ckloopend ;only 1 checksum to do + add esi,8 ;point to the next dword ckloop: - add eax,edx ;cycle 1 U-pipe - mov edx,[esi] ;cycle 1 V-pipe - adc eax,ebx ;cycle 2 U-pipe - mov ebx,[esi+4] ;cycle 2 V-pipe - adc eax,0 ;cycle 3 U-pipe - add esi,8 ;cycle 3 V-pipe - dec ecx ;cycle 4 U-pipe - jnz ckloop ;cycle 4 V-pipe + add eax,edx ;cycle 1 U-pipe + mov edx,[esi] ;cycle 1 V-pipe + adc eax,ebx ;cycle 2 U-pipe + mov ebx,[esi+4] ;cycle 2 V-pipe + adc eax,0 ;cycle 3 U-pipe + add esi,8 ;cycle 3 V-pipe + dec ecx ;cycle 4 U-pipe + jnz ckloop ;cycle 4 V-pipe ckloopend: - add eax,edx ;checksum the last two dwords + add eax,edx ;checksum the last two dwords adc eax,ebx adc eax,0 ckloopdone: - mov edx,eax ;compress the 32-bit checksum - shr edx,16 ; into a 16-bit checksum + mov edx,eax ;compress the 32-bit checksum + shr edx,16 ; into a 16-bit checksum add ax,dx adc eax,0 ``` diff --git a/src/chapter-22.md b/src/chapter-22.md old mode 100644 new mode 100755 index a9f1515..5bf0eee --- a/src/chapter-22.md +++ b/src/chapter-22.md @@ -68,29 +68,29 @@ BufSeg dw ? ;buffer segment EndMrk db ? ;marker for the end of the stack frame OnStack ends ; -ClearS proc near - push bp ;save caller's BP - mov bp,sp ;point to stack frame - cmp word ptr [bp].BufSeg,0 ;skip the fill if a null - jne Start ; pointer is passed - cmp word ptr [bp].BufOfs,0 - je Bye -Start: cld ;make STOSW count up - mov ax,[bp].Attrib ;load AX with attribute parameter - and ax,0ff00h ;prepare for merging with fill char - mov bx,[bp].Filler ;load BX with fill char - and bx,0ffh ;prepare for merging with attribute - or ax,bx ;combine attribute and fill char - mov bx,[bp].BufOfs ;load DI with target buffer offset - mov di,bx - mov bx,[bp].BufSeg ;load ES with target buffer segment - mov es,bx - mov cx,[bp].BufSize ;load CX with buffer size - rep stosw ;fill the buffer -Bye:mov sp,bp ;restore original stack pointer - pop bp ; and caller's BP - ret EndMrk-RetAddr-2 ;return, clearing the parms from the stack -ClearS endp +ClearS proc near + push bp ;save caller's BP + mov bp,sp ;point to stack frame + cmp word ptr [bp].BufSeg,0 ;skip the fill if a null + jne Start ; pointer is passed + cmp word ptr [bp].BufOfs,0 + je Bye +Start: cld ;make STOSW count up + mov ax,[bp].Attrib ;load AX with attribute parameter + and ax,0ff00h ;prepare for merging with fill char + mov bx,[bp].Filler ;load BX with fill char + and bx,0ffh ;prepare for merging with attribute + or ax,bx ;combine attribute and fill char + mov bx,[bp].BufOfs ;load DI with target buffer offset + mov di,bx + mov bx,[bp].BufSeg ;load ES with target buffer segment + mov es,bx + mov cx,[bp].BufSize ;load CX with buffer size + rep stosw ;fill the buffer +Bye: mov sp,bp ;restore original stack pointer + pop bp ; and caller's BP + ret EndMrk-RetAddr-2 ;return, clearing the parms from the stack +ClearS endp ``` The first thing you'll notice about Listing 22.1 is that `ClearS` uses @@ -121,27 +121,27 @@ DI directly as shown in Listing 22.2. **LISTING 22.2 L22-2.ASM** ```nasm -ClearS proc near - push bp ;save caller's BP - mov bp,sp ;point to stack frame - cmp word ptr [bp].BufSeg,0 ;skip the fill if a null - jne Start ; pointer is passed - cmp word ptr [bp].BufOfs,0 - je Bye +ClearS proc near + push bp ;save caller's BP + mov bp,sp ;point to stack frame + cmp word ptr [bp].BufSeg,0 ;skip the fill if a null + jne Start ; pointer is passed + cmp word ptr [bp].BufOfs,0 + je Bye Start: cld ;make STOSW count up - mov ax,[bp].Attrib ;load AX with attribute parameter - and ax,0ff00h ;prepare for merging with fill char - mov bx,[bp].Filler ;load BX with fill char - and bx,0ffh ;prepare for merging with attribute - or ax,bx ;combine attribute and fill char - mov di,[bp].BufOfs ;load DI with target buffer offset - mov es,[bp].BufSeg ;load ES with target buffer segment - mov cx,[bp].BufSize ;load CX with buffer size - rep stosw ;fill the buffer + mov ax,[bp].Attrib ;load AX with attribute parameter + and ax,0ff00h ;prepare for merging with fill char + mov bx,[bp].Filler ;load BX with fill char + and bx,0ffh ;prepare for merging with attribute + or ax,bx ;combine attribute and fill char + mov di,[bp].BufOfs ;load DI with target buffer offset + mov es,[bp].BufSeg ;load ES with target buffer segment + mov cx,[bp].BufSize ;load CX with buffer size + rep stosw ;fill the buffer Bye: - pop bp ;restore caller's BP - ret EndMrk-RetAddr-2 ;return, clearing the parms from the stack -ClearS endp + pop bp ;restore caller's BP + ret EndMrk-RetAddr-2 ;return, clearing the parms from the stack +ClearS endp ``` (The `OnStack` structure definition doesn't change in any of our @@ -158,27 +158,27 @@ loading ES and DI as shown in Listing 22.3. **LISTING 22.3 L22-3.ASM** ```nasm -ClearS proc near - push bp ;save caller's BP - mov bp,sp ;point to stack frame - cmp word ptr [bp].BufSeg,0 ;skip the fill if a null - jne Start ; pointer is passed - cmp word ptr [bp].BufOfs,0 - je Bye +ClearS proc near + push bp ;save caller's BP + mov bp,sp ;point to stack frame + cmp word ptr [bp].BufSeg,0 ;skip the fill if a null + jne Start ; pointer is passed + cmp word ptr [bp].BufOfs,0 + je Bye Start: cld ;make STOSW count up - mov ax,[bp].Attrib ;load AX with attribute parameter - and ax,0ff00h ;prepare for merging with fill char - mov bx,[bp].Filler ;load BX with fill char - and bx,0ffh ;prepare for merging with attribute - or ax,bx ;combine attribute and fill char - les di,dword ptr [bp].BufOfs ;load ES:DI with target buffer + mov ax,[bp].Attrib ;load AX with attribute parameter + and ax,0ff00h ;prepare for merging with fill char + mov bx,[bp].Filler ;load BX with fill char + and bx,0ffh ;prepare for merging with attribute + or ax,bx ;combine attribute and fill char + les di,dword ptr [bp].BufOfs ;load ES:DI with target buffer ;segment:offset - mov cx,[bp].BufSize ;load CX with buffer size - rep stosw ;fill the buffer + mov cx,[bp].BufSize ;load CX with buffer size + rep stosw ;fill the buffer Bye: - pop bp ;restore caller's BP - ret EndMrk-RetAddr-2 ;return, clearing the parms from the stack -ClearS endp + pop bp ;restore caller's BP + ret EndMrk-RetAddr-2 ;return, clearing the parms from the stack +ClearS endp ``` That's good for another three bytes. We're down to 43 bytes, and @@ -190,27 +190,27 @@ values as shown in Listing 22.4. **LISTING 22.4 L22-4.ASM** - ClearS proc near - push bp ;save caller's BP - mov bp,sp ;point to stack frame - cmp word ptr [bp].BufSeg,0 ;skip the fill if a null - jne Start ; pointer is passed - cmp word ptr [bp].BufOfs,0 - je Bye - Start: cld ;make STOSW count up - mov ax,[bp].Attrib ;load AX with attribute parameter - sub al,al ;prepare for merging with fill char - mov bx,[bp].Filler ;load BX with fill char - sub bh,bh ;prepare for merging with attribute - or ax,bx ;combine attribute and fill char - les di,dword ptr [bp].BufOfs ;load ES:DI with target buffer - ;segment:offset - mov cx,[bp].BufSize ;load CX with buffer size - rep stosw ;fill the buffer + ClearS proc near + push bp ;save caller's BP + mov bp,sp ;point to stack frame + cmp word ptr [bp].BufSeg,0 ;skip the fill if a null + jne Start ; pointer is passed + cmp word ptr [bp].BufOfs,0 + je Bye + Start: cld ;make STOSW count up + mov ax,[bp].Attrib ;load AX with attribute parameter + sub al,al ;prepare for merging with fill char + mov bx,[bp].Filler ;load BX with fill char + sub bh,bh ;prepare for merging with attribute + or ax,bx ;combine attribute and fill char + les di,dword ptr [bp].BufOfs ;load ES:DI with target buffer + ;segment:offset + mov cx,[bp].BufSize ;load CX with buffer size + rep stosw ;fill the buffer Bye: - pop bp ;restore caller's BP - ret EndMrk-RetAddr-2 ;return, clearing the parms from the stack - ClearS endp + pop bp ;restore caller's BP + ret EndMrk-RetAddr-2 ;return, clearing the parms from the stack + ClearS endp Now we're down to 40 bytes—more than 20 percent smaller than the original code. That's pretty much it for simple instruction @@ -232,23 +232,23 @@ shows the new code. **LISTING 22.5 L22-5.ASM** ```nasm -ClearS proc near - push bp ;save caller's BP - mov bp,sp ;point to stack frame - cmp word ptr [bp].BufSeg,0 ;skip the fill if a null - jne Start ; pointer is passed - cmp word ptr [bp].BufOfs,0 - je Bye -Start: cld ;make STOSW count up - mov ah,byte ptr [bp].Attrib[1];load AH with attribute - mov al,byte ptr [bp].Filler ;load AL with fill char - les di,dword ptr [bp].BufOfs ;load ES:DI with target buffer segment:offset - mov cx,[bp].BufSize ;load CX with buffer size - rep stosw ;fill the buffer +ClearS proc near + push bp ;save caller's BP + mov bp,sp ;point to stack frame + cmp word ptr [bp].BufSeg,0 ;skip the fill if a null + jne Start ; pointer is passed + cmp word ptr [bp].BufOfs,0 + je Bye +Start: cld ;make STOSW count up + mov ah,byte ptr [bp].Attrib[1] ;load AH with attribute + mov al,byte ptr [bp].Filler ;load AL with fill char + les di,dword ptr [bp].BufOfs ;load ES:DI with target buffer segment:offset + mov cx,[bp].BufSize ;load CX with buffer size + rep stosw ;fill the buffer Bye: - pop bp ;restore caller's BP - ret EndMrk-RetAddr-2 ;return, clearing the parms from the stack -ClearS endp + pop bp ;restore caller's BP + ret EndMrk-RetAddr-2 ;return, clearing the parms from the stack +ClearS endp ``` (We could get rid of yet another instruction by having the calling code @@ -266,22 +266,22 @@ shown in Listing 22.6. **LISTING 22.6 L22-6.ASM** ```nasm -ClearS proc near - push bp ;save caller's BP - mov bp,sp ;point to stack frame - les di,dword ptr [bp].BufOfs ;load ES:DI with target buffer;segment:offset - mov ax,es ;put segment where we can test it - or ax,di ;is it a null pointer? - je Bye ;yes, so we're done -Start: cld ;make STOSW count up - mov ah,byte ptr [bp].Attrib[1];load AH with attribute - mov al,byte ptr [bp].Filler ;load AL with fill char - mov cx,[bp].BufSize ;load CX with buffer size - rep stosw ;fill the buffer +ClearS proc near + push bp ;save caller's BP + mov bp,sp ;point to stack frame + les di,dword ptr [bp].BufOfs ;load ES:DI with target buffer;segment:offset + mov ax,es ;put segment where we can test it + or ax,di ;is it a null pointer? + je Bye ;yes, so we're done +Start: cld ;make STOSW count up + mov ah,byte ptr [bp].Attrib[1] ;load AH with attribute + mov al,byte ptr [bp].Filler ;load AL with fill char + mov cx,[bp].BufSize ;load CX with buffer size + rep stosw ;fill the buffer Bye: - pop bp ;restore caller's BP - ret EndMrk-RetAddr-2 ;return, clearing the parms from the stack -ClearS endp + pop bp ;restore caller's BP + ret EndMrk-RetAddr-2 ;return, clearing the parms from the stack +ClearS endp ``` Well. Now we're down to 28 bytes, having reduced the size of this @@ -327,22 +327,22 @@ With that problem dealt with, Listing 22.7 shows the Zenned version of **LISTING 22.7 L22-7.ASM** ```nasm -ClearS procnear - pop dx ;get the return address - pop ax ;put fill char into AL - pop bx ;get the attribute - mov ah,bh ;put attribute into AH - pop cx ;get the buffer size - pop di ;get the offset of the buffer origin - pop es ;get the segment of the buffer origin - mov bx,es ;put the segment where we can test it - or bx,di ;null pointer? - je Bye ;yes, so we're done - cld ;make STOSW count up - rep stosw ;do the string store +ClearS proc near + pop dx ;get the return address + pop ax ;put fill char into AL + pop bx ;get the attribute + mov ah,bh ;put attribute into AH + pop cx ;get the buffer size + pop di ;get the offset of the buffer origin + pop es ;get the segment of the buffer origin + mov bx,es ;put the segment where we can test it + or bx,di ;null pointer? + je Bye ;yes, so we're done + cld ;make STOSW count up + rep stosw ;do the string store Bye: - jmp dx ;return to the calling code -ClearS endp + jmp dx ;return to the calling code +ClearS endp ``` At long last, we're down to the bare metal. This version of `ClearS`