xref: /reactos/sdk/lib/ucrt/string/i386/strncpy.s (revision 94eb4751)
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