reactos/sdk/lib/ucrt/string/i386/strncat.s
2025-01-22 18:56:08 +02:00

255 lines
7.2 KiB
ArmAsm

#include <asm.inc>
#if 0
page ,132
title strncat - append n chars of string1 to string2
;***
;strncat.asm - append n chars of string to new string
;
; Copyright (c) Microsoft Corporation. All rights reserved.
;
;Purpose:
; defines strncat() - appends n characters of string onto
; end of other string
;
;*******************************************************************************
.xlist
include cruntime.inc
.list
page
;***
;char *strncat(front, back, count) - append count chars of back onto front
;
;Purpose:
; Appends at most count characters of the string back onto the
; end of front, and ALWAYS terminates with a null character.
; If count is greater than the length of back, the length of back
; is used instead. (Unlike strncpy, this routine does not pad out
; to count characters).
;
; Algorithm:
; char *
; strncat (front, back, count)
; char *front, *back;
; unsigned count;
; {
; char *start = front;
;
; while (*front++)
; ;
; front--;
; while (count--)
; if (!(*front++ = *back++))
; return(start);
; *front = '\0';
; return(start);
; }
;
;Entry:
; char * front - string to append onto
; char * back - string to append
; unsigned count - count of max characters to append
;
;Exit:
; returns a pointer to string appended onto (front).
;
;Uses: ECX, EDX
;
;Exceptions:
;
;*******************************************************************************
#endif
.code
public _strncat
.PROC _strncat
// front:ptr byte,
// back:ptr byte,
// count:IWORD
FPO 0, 3, 0, 0, 0, 0
mov ecx,[esp + HEX(0c)] // ecx = count
push edi // preserve edi
test ecx,ecx
jz finish // leave if count is zero
mov edi,[esp + 8] // edi -> front string
push esi // preserve esi
test edi,3 // is string aligned on dword (4 bytes)
push ebx // preserve ebx
je short find_end_of_front_string_loop
// simple byte loop until string is aligned
front_misaligned:
mov al,byte ptr [edi]
add edi,1
test al,al
je short start_byte_3
test edi,3
jne short front_misaligned
find_end_of_front_string_loop:
mov eax,dword ptr [edi] // read dword (4 bytes)
mov edx,HEX(7efefeff)
add edx,eax
xor eax,-1
xor eax,edx
add edi,4
test eax,HEX(81010100)
je short find_end_of_front_string_loop
// found zero byte in the loop
mov eax,[edi - 4]
test al,al // is it byte 0
je short start_byte_0
test ah,ah // is it byte 1
je short start_byte_1
test eax,HEX(00ff0000) // is it byte 2
je short start_byte_2
test eax,HEX(0ff000000) // is it byte 3
jne short find_end_of_front_string_loop
// taken if bits 24-30 are clear and bit
// 31 is set
start_byte_3:
sub edi,1
jmp short copy_start
start_byte_2:
sub edi,2
jmp short copy_start
start_byte_1:
sub edi,3
jmp short copy_start
start_byte_0:
sub edi,4
// edi now points to the end of front string.
copy_start:
mov esi,[esp + HEX(14)] // esi -> back string
test esi,3 // is back string is dword aligned?
jnz back_misaligned
mov ebx,ecx // store count for tail loop
shr ecx,2
jnz short main_loop_entrance
jmp short tail_loop_start // 0 < counter < 4
// simple byte loop until back string is aligned
back_misaligned:
mov dl,byte ptr [esi]
add esi,1
test dl,dl
je short byte_0
mov [edi],dl
add edi,1
sub ecx,1
jz empty_counter
test esi,3
jne short back_misaligned
mov ebx,ecx // store count for tail loop
shr ecx,2 // convert ecx to dword count
jnz short main_loop_entrance
tail_loop_start:
mov ecx,ebx
and ecx,3 // ecx = count of leftover bytes after the
// dwords have been concatenated
jz empty_counter
tail_loop:
mov dl,byte ptr [esi]
add esi,1
mov [edi],dl
add edi,1
test dl,dl
je short finish1 // '\0' was already copied
sub ecx,1
jnz tail_loop
empty_counter:
mov [edi],cl // cl=0;
finish1:
pop ebx
pop esi
finish:
mov eax,[esp + 8] // return in eax pointer to front string
pop edi
ret // _cdecl return
byte_0:
mov [edi],dl
mov eax,[esp + HEX(10)] // return in eax pointer to front string
pop ebx
pop esi
pop edi
ret // _cdecl return
main_loop: // edx contains first dword of back string
mov [edi],edx // store one more dword
add edi,4 // kick pointer to front string
sub ecx,1
jz tail_loop_start
main_loop_entrance:
mov edx,HEX(7efefeff)
mov eax,dword ptr [esi] // read 4 bytes
add edx,eax
xor eax,-1
xor eax,edx
mov edx,[esi] // it's in cache now
add esi,4 // kick pointer to back string
test eax,HEX(81010100)
je short main_loop
// may be found zero byte in the loop
test dl,dl // is it byte 0
je short byte_0
test dh,dh // is it byte 1
je short byte_1
test edx,HEX(00ff0000) // is it byte 2
je short byte_2
test edx,HEX(0ff000000) // is it byte 3
jne short main_loop // taken if bits 24-30 are clear and bit
// 31 is set
byte_3:
mov [edi],edx
mov eax,[esp + HEX(10)] // return in eax pointer to front string
pop ebx
pop esi
pop edi
ret // _cdecl return
byte_2:
mov [edi],dx
xor edx,edx
mov eax,[esp + HEX(10)] // return in eax pointer to front string
mov [edi + 2],dl
pop ebx
pop esi
pop edi
ret // _cdecl return
byte_1:
mov [edi],dx
mov eax,[esp + HEX(10)] // return in eax pointer to front string
pop ebx
pop esi
pop edi
ret // _cdecl return
.ENDP // _strncat
end