1#include <asm.inc> 2#if 0 3 page ,132 4 title strncpy - copy at most n characters of string 5;*** 6;strncpy.asm - copy at most n characters of string 7; 8; Copyright (c) Microsoft Corporation. All rights reserved. 9; 10;Purpose: 11; defines strncpy() - copy at most n characters of string 12; 13;******************************************************************************* 14 15 .xlist 16 include cruntime.inc 17 .list 18 19page 20;*** 21;char *strncpy(dest, source, count) - copy at most n characters 22; 23;Purpose: 24; Copies count characters from the source string to the 25; destination. If count is less than the length of source, 26; NO NULL CHARACTER is put onto the end of the copied string. 27; If count is greater than the length of sources, dest is padded 28; with null characters to length count. 29; 30; Algorithm: 31; char * 32; strncpy (dest, source, count) 33; char *dest, *source; 34; unsigned count; 35; { 36; char *start = dest; 37; 38; while (count && (*dest++ = *source++)) 39; count--; 40; if (count) 41; while (--count) 42; *dest++ = '\0'; 43; return(start); 44; } 45; 46;Entry: 47; char *dest - pointer to spot to copy source, enough space 48; is assumed. 49; char *source - source string for copy 50; unsigned count - characters to copy 51; 52;Exit: 53; returns dest, with the character copied there. 54; 55;Uses: 56; 57;Exceptions: 58; 59;******************************************************************************* 60#endif 61 62 .code 63 64 public _strncpy 65.PROC _strncpy 66 // dest:ptr byte, \ 67 // source:ptr byte, \ 68 // count:dword 69 70 //OPTION PROLOGUE:NONE, EPILOGUE:NONE 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 push esi // preserve edi 80 push ebx // preserve ebx 81 mov ebx,ecx // store count for tail loop 82 mov esi,[esp + HEX(14)] // esi -> source string 83 test esi,3 // test if source string is aligned on 32 bits 84 mov edi,[esp + HEX(10)] // edi -> dest string 85 jnz short src_misaligned // (almost always source is aligned) 86 87 shr ecx,2 // convert ecx to dword count 88 jnz main_loop_entrance 89 jmp short copy_tail_loop // 0 < count < 4 90 91// simple byte loop until string is aligned 92 93src_misaligned: 94 mov al,byte ptr [esi] // copy a byte from source to dest 95 add esi,1 96 mov [edi],al 97 add edi,1 98 sub ecx,1 99 jz fill_tail_end1 // if count == 0, leave 100 test al,al // was last copied byte zero? 101 jz short align_dest // if so, go align dest and pad it out 102 // with zeros 103 test esi,3 // esi already aligned ? 104 jne short src_misaligned 105 mov ebx,ecx // store count for tail loop 106 shr ecx,2 107 jnz short main_loop_entrance 108 109tail_loop_start: 110 and ebx,3 // ebx = count_before_main_loop%4 111 jz short fill_tail_end1 // if ebx == 0 then leave without 112 // appending a null byte 113 114// while ( EOS (end-of-string) not found and count > 0 ) copy bytes 115 116copy_tail_loop: 117 mov al,byte ptr [esi] // load byte from source 118 add esi,1 119 mov [edi],al // store byte to dest 120 add edi,1 121 test al,al // EOS found? 122 je short fill_tail_zero_bytes // '\0' was already copied 123 sub ebx,1 124 jnz copy_tail_loop 125fill_tail_end1: 126 mov eax,[esp + HEX(10)] // prepare return value 127 pop ebx 128 pop esi 129 pop edi 130 ret 131 132// EOS found. Pad with null characters to length count 133 134align_dest: 135 test edi,3 // dest string aligned? 136 jz dest_align_loop_end 137dest_align_loop: 138 mov [edi],al 139 add edi,1 140 sub ecx,1 // count == 0? 141 jz fill_tail_end // if so, finished 142 test edi,3 // is edi aligned ? 143 jnz dest_align_loop 144dest_align_loop_end: 145 mov ebx,ecx // ebx > 0 146 shr ecx,2 // convert ecx to count of dwords 147 jnz fill_dwords_with_EOS 148 // pad tail bytes 149finish_loop: // 0 < ebx < 4 150 mov [edi],al 151 add edi,1 152fill_tail_zero_bytes: 153 sub ebx,1 154 jnz finish_loop 155 pop ebx 156 pop esi 157finish: 158 mov eax,[esp + 8] // return in eax pointer to dest string 159 pop edi 160 ret 161 162// copy (source) string to (dest). Also look for end of (source) string 163 164main_loop: // edx contains first dword of source string 165 mov [edi],edx // store one more dword 166 add edi,4 // kick dest pointer 167 sub ecx,1 168 jz tail_loop_start 169 170main_loop_entrance: 171 mov edx,HEX(7efefeff) 172 mov eax,dword ptr [esi] // read 4 bytes (dword) 173 add edx,eax 174 xor eax,-1 175 xor eax,edx 176 mov edx,[esi] // it's in cache now 177 add esi,4 // kick dest pointer 178 test eax,HEX(81010100) 179 je short main_loop 180 181 // may have found zero byte in the dword 182 183 test dl,dl // is it byte 0 184 je short byte_0 185 test dh,dh // is it byte 1 186 je short byte_1 187 test edx,HEX(00ff0000) // is it byte 2 188 je short byte_2 189 test edx,HEX(0ff000000) // is it byte 3 190 jne short main_loop // taken if bits 24-30 are clear and bit 191 // 31 is set 192 193// a null character was found, so dest needs to be padded out with null chars 194// to count length. 195 196 mov [edi],edx 197 jmp short fill_with_EOS_dwords 198 199byte_2: 200 and edx,HEX(0ffff) // fill high 2 bytes with 0 201 mov [edi],edx 202 jmp short fill_with_EOS_dwords 203 204byte_1: 205 and edx,HEX(0ff) // fill high 3 bytes with 0 206 mov [edi],edx 207 jmp short fill_with_EOS_dwords 208 209byte_0: 210 xor edx,edx // fill whole dword with 0 211 mov [edi],edx 212 213// End of string was found. Pad out dest string with dwords of 0 214 215fill_with_EOS_dwords: // ecx > 0 (ecx is dword counter) 216 add edi,4 217 xor eax,eax // it is instead of ??????????????????? 218 sub ecx,1 219 jz fill_tail // we filled all dwords 220 221fill_dwords_with_EOS: 222 xor eax,eax 223fill_with_EOS_loop: 224 mov [edi],eax 225 add edi,4 226 sub ecx,1 227 jnz short fill_with_EOS_loop 228fill_tail: // let's pad tail bytes with zero 229 and ebx,3 // ebx = ebx % 4 230 jnz finish_loop // taken, when there are some tail bytes 231fill_tail_end: 232 mov eax,[esp + HEX(10)] 233 pop ebx 234 pop esi 235 pop edi 236 ret 237 238.ENDP // _strncpy 239 end 240 241 242 243