_80x86 OPTIMIZATION_ by Michael Abrash [LISTING ONE] ; Copies one string to another string, converting all characters to ; uppercase in the process, using a loop containing LODSB and STOSB. ; Adapted from Zen of Assembly Language, by Michael Abrash; not a ; standalone program, but designed to be used with the Zen timer from ; that book via the Zen timer's PZTIME.BAT batch file: ZTimerOn starts ; the clock, ZTimerOff stops it, and the test-bed program linked in by ; PZTIME.BAT starts the program, reports the results, and ends. jmp Skip ;skip over data in CS and subroutine SourceString label word ;sample string to copy db 'This space intentionally left not blank',0 DestString db 100 dup (?) ;destination for copy ; Copies one zero-terminated string to another string, ; converting all characters to uppercase. ; Input: DS:SI = start of source string; DS:DI = start of destination buffer ; Output: none ; Registers altered: AX, BX, SI, DI, ES ; Direction flag cleared CopyStringUpper: mov ax,ds mov es,ax ;for STOS mov bl,'a' ;set up for fast register-register mov bh,'z' ; comparisons cld StringUpperLoop: lodsb ;get next character and point to following character cmp al,bl ;below 'a'? jb IsUpper ;yes, not lowercase cmp al,bh ;above 'z'? ja IsUpper ;yes, not lowercase and al,not 20h ;is lowercase-make uppercase IsUpper: stosb ;put character into new string and point to ; following location and al,al ;is this the zero that marks end of the string? jnz StringUpperLoop ;no, do the next character ret ; Calls CopyStringUpper to copy & convert SourceString->DestString. Skip: call ZTimerOn ;start timing mov si,offset SourceString ;point SI to the string to copy from mov di,offset DestString ;point DI to the string to copy to call CopyStringUpper ;copy & convert to uppercase call ZTimerOff ;stop timing [LISTING TWO] ; Copies one string to another string, converting all characters to ; uppercase in the process, using no string instructions. ; Not a standalone program, but designed to be used with the Zen ; timer, as described in Listing 1. jmp Skip ;skip over data in CS and subroutine SourceString label word ;sample string to copy db 'This space intentionally left not blank',0 DestString db 100 dup (?) ;destination for copy ; Copies one zero-terminated string to another string, ; converting all characters to uppercase. ; Input: DS:SI = start of source string; DS:DI = start of destination string ; Output: none ; Registers altered: AL, BX, SI, DI CopyStringUpper: mov bl,'a' ;set up for fast register-register mov bh,'z' ; comparisons StringUpperLoop: mov al,[si] ;get the next character and inc si ; point to the following character cmp al,bl ;below 'a'? jb IsUpper ;yes, not lowercase cmp al,bh ;above 'z'? ja IsUpper ;yes, not lowercase and al,not 20h ;is lowercase-make uppercase IsUpper: mov [di],al ;put the character into the new string and inc di ; point to the following location and al,al ;is this the zero that marks the end of the string? jnz StringUpperLoop ;no, do the next character ret ; Calls CopyStringUpper to copy & convert SourceString->DestString. Skip: call ZTimerOn mov si,offset SourceString ;point SI to the string to copy from mov di,offset DestString ;point DI to the string to copy to call CopyStringUpper ;copy & convert to uppercase call ZTimerOff [LISTING THREE] ; Clears a buffer using MOV/ADD in a loop. ; Not a standalone program, but designed to be used with the Zen ; timer, as described in Listing 1. mov dx,2 ;repeat the test code twice, to make ; sure it's in the cache (if there is one) mov bx,dx ;distance from the start of one word ; to the start of the next sub ax,ax ;set buffer to zeroes TestTwiceLoop: mov cx,1024 ;clear 1024 words starting at address mov di,8000h ; DS:8000h (this is just unused memory ; past the end of the program) call ZTimerOn ;start timing (resets timer to 0) StoreLoop: mov [di],ax ;clear the current word add di,bx ;point to the next word dec cx ;count off words to clear until none jnz StoreLoop ; remain call ZTimerOff ;stop timing dec dx ;count off passes through test code jz StoreDone ;that was the second pass; we're done jmp TestTwiceLoop ;that was first pass; do second pass with all ; instructions and data in the cache StoreDone: [LISTING FOUR] ; Clears a buffer using MOV/ADD in an unrolled loop. ; Not a standalone program, but designed to be used with the Zen ; timer, as described in Listing 1. mov dx,2 ;repeat the test code twice, to make ; sure it's in the cache (if there is one) mov bx,dx ;distance from the start of one word ; to the start of the next sub ax,ax ;set buffer to zeroes TestTwiceLoop: mov si,1024 ;clear 1024 words starting at address mov di,8000h ; DS:8000h (this is just unused memory ; past the end of the program) call ZTimerOn ;start timing (resets timer to 0) mov cl,4 ;divide the count of words to clear by shr si,cl ; 16, because we'll clear 16 words ; each time through the loop StoreLoop: REPT 16 ;clear 16 words in a row without looping mov [di],ax ;clear the current word add di,bx ;point to the next word ENDM dec si ;count off blocks of 16 words to clear jnz StoreLoop ; until none remain call ZTimerOff ;stop timing dec dx ;count off passes through test code jz StoreDone ;that was the second pass; we're done jmp TestTwiceLoop ;that was the first pass; do the second pass ; with all instructions and data in the cache StoreDone: