5.2 Array/String Instructions
5.2.4 The REPx instruction prefixes
There are several other REP-like instruction prefixes that can be used with the comparison string instructions. Figure 5.12 shows the two new prefixes and describes their operation. REPE and REPZ are just synonyms for the same prefix (as are REPNE and REPNZ). If the repeated comparison string instruction stops because of the result of the comparison, the index register or registers are still incremented and ECX decremented; however, the FLAGS register still holds the state that terminated the repetition. Thus, it is possible to use the Z flag to determine if the repeated comparisons
Why can one not just look to see if ECX is zero after the repeated comparison?
stopped because of a comparison or ECX becoming zero.
Figure 5.13 shows an example code snippet that determines if two blocks of memory are equal. TheJEon line 7 of the example checks to see the result of the previous instruction. If the repeated comparison stopped because it found two unequal bytes, the Z flag will still be cleared and no branch is made; however, if the comparisons stopped because ECX became zero, the Z flag will still be set and the code branches to theequal label.
5.2.5 Example
This section contains an assembly source file with several functions that implement array operations using string instructions. Many of the functions duplicate familiar C library functions.
1 segment .bss
2 array resd 100
3
4 segment .text
5 cld
6 mov edi, array ; pointer to start of array
7 mov ecx, 100 ; number of elements
8 mov eax, 12 ; number to scan for
9 lp:
10 scasd
11 je found
12 loop lp
13 ; code to perform if not found
14 jmp onward
15 found:
16 sub edi, 4 ; edi now points to 12 in array
17 ; code to perform if found 18 onward:
Figure 5.11: Search example
REPE,REPZ repeats instruction while Z flag is set or at most ECX times REPNE,REPNZ repeats instruction while Z flag is cleared or at most ECX
times
Figure 5.12: REPx instruction prefixes
1 global _asm_copy, _asm_find, _asm_strlen, _asm_strcpy 2
3 segment .text
4 ; function _asm_copy 5 ; copies blocks of memory 6 ; C prototype
7 ; void asm_copy( void * dest, const void * src, unsigned sz); 8 ; parameters:
9 ; dest - pointer to buffer to copy to 10 ; src - pointer to buffer to copy from 11 ; sz - number of bytes to copy
12
13 ; next, some helpful symbols are defined 14
1 segment .text
2 cld
3 mov esi, block1 ; address of first block
4 mov edi, block2 ; address of second block
5 mov ecx, size ; size of blocks in bytes
6 repe cmpsb ; repeat while Z flag is set
7 je equal ; if Z set, blocks equal
8 ; code to perform if blocks are not equal
9 jmp onward
10 equal:
11 ; code to perform if equal 12 onward:
Figure 5.13: Comparing memory blocks
15 %define dest [ebp+8] 16 %define src [ebp+12] 17 %define sz [ebp+16] 18 _asm_copy: 19 enter 0, 0 20 push esi 21 push edi 22
23 mov esi, src ; esi = address of buffer to copy from
24 mov edi, des ; edi = address of buffer to copy to
25 mov ecx, sz ; ecx = number of bytes to copy
26
27 cld ; clear direction flag
28 rep movsb ; execute movsb ECX times
29 30 pop edi 31 pop esi 32 leave 33 ret 34 35 36 ; function _asm_find
37 ; searches memory for a given byte
38 ; void * asm_find( const void * src, char target, unsigned sz); 39 ; parameters:
40 ; src - pointer to buffer to search 41 ; target - byte value to search for 42 ; sz - number of bytes in buffer 43 ; return value:
44 ; if target is found, pointer to first occurrence of target in buffer 45 ; is returned
46 ; else
47 ; NULL is returned
48 ; NOTE: target is a byte value, but is pushed on stack as a dword value. 49 ; The byte value is stored in the lower 8-bits.
50 ;
51 %define src [ebp+8] 52 %define target [ebp+12] 53 %define sz [ebp+16] 54 55 _asm_find: 56 enter 0,0 57 push edi 58
59 mov eax, target ; al has value to search for
60 mov edi, src
61 mov ecx, sz
62 cld
63
64 repne scasb ; scan until ECX == 0 or [ES:EDI] == AL
65
66 je found_it ; if zero flag set, then found value
67 mov eax, 0 ; if not found, return NULL pointer
68 jmp short quit
69 found_it:
70 mov eax, edi
71 dec eax ; if found return (DI - 1)
72 quit: 73 pop edi 74 leave 75 ret 76 77 78 ; function _asm_strlen
79 ; returns the size of a string
80 ; unsigned asm_strlen( const char * ); 81 ; parameter:
82 ; src - pointer to string 83 ; return value:
84 ; number of chars in string (not counting, ending 0) (in EAX) 85 86 %define src [ebp + 8] 87 _asm_strlen: 88 enter 0,0 89 push edi 90
91 mov edi, src ; edi = pointer to string
92 mov ecx, 0FFFFFFFFh ; use largest possible ECX
93 xor al,al ; al = 0
94 cld
95
96 repnz scasb ; scan for terminating 0
97 98 ;
99 ; repnz will go one step too far, so length is FFFFFFFE - ECX, 100 ; not FFFFFFFF - ECX
101 ;
102 mov eax,0FFFFFFFEh
103 sub eax, ecx ; length = 0FFFFFFFEh - ecx
104 105 pop edi 106 leave 107 ret 108 109 ; function _asm_strcpy 110 ; copies a string
111 ; void asm_strcpy( char * dest, const char * src); 112 ; parameters:
113 ; dest - pointer to string to copy to 114 ; src - pointer to string to copy from 115 ;
116 %define dest [ebp + 8] 117 %define src [ebp + 12] 118 _asm_strcpy: 119 enter 0,0 120 push esi 121 push edi 122
124 mov esi, src
125 cld
126 cpy_loop:
127 lodsb ; load AL & inc si
128 stosb ; store AL & inc di
129 or al, al ; set condition flags
130 jnz cpy_loop ; if not past terminating 0, continue
131 132 pop edi 133 pop esi 134 leave 135 ret memory.asm memex.c 1 #include <stdio.h> 2 3 #defineSTR SIZE 30 4 /∗ prototypes ∗/ 5
6 void asm copy( void ∗, const void ∗, unsigned) attribute ((cdecl)); 7 void ∗ asm find ( const void ∗,
8 char target , unsigned ) attribute ((cdecl)); 9 unsigned asm strlen( const char ∗ ) attribute ((cdecl)); 10 void asm strcpy ( char ∗, const char ∗ ) attribute ((cdecl)); 11
12 int main() 13 {
14 char st1 [STR SIZE] = ”test string”; 15 char st2 [STR SIZE];
16 char ∗ st ; 17 char ch; 18
19 asm copy(st2, st1 , STR SIZE); /∗ copy all 30 chars of string ∗/ 20 printf (”%s\n”, st2);
21
22 printf (”Enter a char : ” ); /∗ look for byte in string ∗/ 23 scanf (”%c%∗[ˆ\n]”, &ch);
24 st = asm find(st2 , ch , STR SIZE); 25 if ( st )
26 printf (”Found it: %s\n”, st ); 27 else
29
30 st1 [0] = 0;
31 printf (”Enter string :” ); 32 scanf (”%s”, st1 );
33 printf (”len = %u\n”, asm strlen(st1 )); 34
35 asm strcpy ( st2 , st1 ); /∗ copy meaningful data in string ∗/ 36 printf (”%s\n”, st2 );
37
38 return 0; 39 }