1#include <asm.inc> 2#if 0 3 page ,132 4 title strncat - append n chars of string1 to string2 5;*** 6;strncat.asm - append n chars of string to new string 7; 8; Copyright (c) Microsoft Corporation. All rights reserved. 9; 10;Purpose: 11; defines strncat() - appends n characters of string onto 12; end of other string 13; 14;******************************************************************************* 15 16 .xlist 17 include cruntime.inc 18 .list 19 20page 21;*** 22;char *strncat(front, back, count) - append count chars of back onto front 23; 24;Purpose: 25; Appends at most count characters of the string back onto the 26; end of front, and ALWAYS terminates with a null character. 27; If count is greater than the length of back, the length of back 28; is used instead. (Unlike strncpy, this routine does not pad out 29; to count characters). 30; 31; Algorithm: 32; char * 33; strncat (front, back, count) 34; char *front, *back; 35; unsigned count; 36; { 37; char *start = front; 38; 39; while (*front++) 40; ; 41; front--; 42; while (count--) 43; if (!(*front++ = *back++)) 44; return(start); 45; *front = '\0'; 46; return(start); 47; } 48; 49;Entry: 50; char * front - string to append onto 51; char * back - string to append 52; unsigned count - count of max characters to append 53; 54;Exit: 55; returns a pointer to string appended onto (front). 56; 57;Uses: ECX, EDX 58; 59;Exceptions: 60; 61;******************************************************************************* 62#endif 63 64 .code 65 66 public _strncat 67.PROC _strncat 68 // front:ptr byte, 69 // back:ptr byte, 70 // count:IWORD 71 72 FPO 0, 3, 0, 0, 0, 0 73 74 mov ecx,[esp + HEX(0c)] // ecx = count 75 push edi // preserve edi 76 test ecx,ecx 77 jz finish // leave if count is zero 78 79 mov edi,[esp + 8] // edi -> front string 80 push esi // preserve esi 81 test edi,3 // is string aligned on dword (4 bytes) 82 push ebx // preserve ebx 83 je short find_end_of_front_string_loop 84 85 // simple byte loop until string is aligned 86 87front_misaligned: 88 mov al,byte ptr [edi] 89 add edi,1 90 test al,al 91 je short start_byte_3 92 test edi,3 93 jne short front_misaligned 94 95find_end_of_front_string_loop: 96 mov eax,dword ptr [edi] // read dword (4 bytes) 97 mov edx,HEX(7efefeff) 98 add edx,eax 99 xor eax,-1 100 xor eax,edx 101 add edi,4 102 test eax,HEX(81010100) 103 je short find_end_of_front_string_loop 104 105// found zero byte in the loop 106 mov eax,[edi - 4] 107 test al,al // is it byte 0 108 je short start_byte_0 109 test ah,ah // is it byte 1 110 je short start_byte_1 111 test eax,HEX(00ff0000) // is it byte 2 112 je short start_byte_2 113 test eax,HEX(0ff000000) // is it byte 3 114 jne short find_end_of_front_string_loop 115 // taken if bits 24-30 are clear and bit 116 // 31 is set 117start_byte_3: 118 sub edi,1 119 jmp short copy_start 120start_byte_2: 121 sub edi,2 122 jmp short copy_start 123start_byte_1: 124 sub edi,3 125 jmp short copy_start 126start_byte_0: 127 sub edi,4 128 129// edi now points to the end of front string. 130 131copy_start: 132 mov esi,[esp + HEX(14)] // esi -> back string 133 test esi,3 // is back string is dword aligned? 134 jnz back_misaligned 135 136 mov ebx,ecx // store count for tail loop 137 138 shr ecx,2 139 jnz short main_loop_entrance 140 jmp short tail_loop_start // 0 < counter < 4 141 142// simple byte loop until back string is aligned 143 144back_misaligned: 145 mov dl,byte ptr [esi] 146 add esi,1 147 test dl,dl 148 je short byte_0 149 mov [edi],dl 150 add edi,1 151 sub ecx,1 152 jz empty_counter 153 test esi,3 154 jne short back_misaligned 155 mov ebx,ecx // store count for tail loop 156 shr ecx,2 // convert ecx to dword count 157 jnz short main_loop_entrance 158 159tail_loop_start: 160 mov ecx,ebx 161 and ecx,3 // ecx = count of leftover bytes after the 162 // dwords have been concatenated 163 jz empty_counter 164 165tail_loop: 166 mov dl,byte ptr [esi] 167 add esi,1 168 mov [edi],dl 169 add edi,1 170 test dl,dl 171 je short finish1 // '\0' was already copied 172 sub ecx,1 173 jnz tail_loop 174 175empty_counter: 176 mov [edi],cl // cl=0; 177finish1: 178 pop ebx 179 pop esi 180finish: 181 mov eax,[esp + 8] // return in eax pointer to front string 182 pop edi 183 ret // _cdecl return 184 185 186byte_0: 187 mov [edi],dl 188 mov eax,[esp + HEX(10)] // return in eax pointer to front string 189 pop ebx 190 pop esi 191 pop edi 192 ret // _cdecl return 193 194 195main_loop: // edx contains first dword of back string 196 mov [edi],edx // store one more dword 197 add edi,4 // kick pointer to front string 198 199 sub ecx,1 200 jz tail_loop_start 201main_loop_entrance: 202 mov edx,HEX(7efefeff) 203 mov eax,dword ptr [esi] // read 4 bytes 204 205 add edx,eax 206 xor eax,-1 207 208 xor eax,edx 209 mov edx,[esi] // it's in cache now 210 211 add esi,4 // kick pointer to back string 212 test eax,HEX(81010100) 213 214 je short main_loop 215 216// may be found zero byte in the loop 217 test dl,dl // is it byte 0 218 je short byte_0 219 test dh,dh // is it byte 1 220 je short byte_1 221 test edx,HEX(00ff0000) // is it byte 2 222 je short byte_2 223 test edx,HEX(0ff000000) // is it byte 3 224 jne short main_loop // taken if bits 24-30 are clear and bit 225 // 31 is set 226byte_3: 227 mov [edi],edx 228 mov eax,[esp + HEX(10)] // return in eax pointer to front string 229 pop ebx 230 pop esi 231 pop edi 232 ret // _cdecl return 233 234byte_2: 235 mov [edi],dx 236 xor edx,edx 237 mov eax,[esp + HEX(10)] // return in eax pointer to front string 238 mov [edi + 2],dl 239 pop ebx 240 pop esi 241 pop edi 242 ret // _cdecl return 243 244byte_1: 245 mov [edi],dx 246 mov eax,[esp + HEX(10)] // return in eax pointer to front string 247 pop ebx 248 pop esi 249 pop edi 250 ret // _cdecl return 251 252.ENDP // _strncat 253 254 end 255 256