/drivers/ddk/string/_memmove.S |
---|
0,0 → 1,67 |
# _memmove() Author: Kees J. Bot 2 Jan 1994 |
# void *_memmove(void *s1, const void *s2, size_t n) |
# Copy a chunk of memory. Handle overlap. |
.intel_syntax |
.globl __memmove, __memcpy |
.text |
.align 16 |
__memmove: |
push ebp |
mov ebp, esp |
push esi |
push edi |
mov edi, [ebp+8] # String s1 |
mov esi, [ebp+12] # String s2 |
mov ecx, [ebp+16] # Length |
mov eax, edi |
sub eax, esi |
cmp eax, ecx |
jb downwards # if (s2 - s1) < n then copy downwards |
__memcpy: |
cld # Clear direction bit: upwards |
cmp ecx, 16 |
jb upbyte # Don't bother being smart with short arrays |
mov eax, esi |
or eax, edi |
testb al, 1 |
jnz upbyte # Bit 0 set, use byte copy |
testb al, 2 |
jnz upword # Bit 1 set, use word copy |
uplword: |
shrd eax, ecx, 2 # Save low 2 bits of ecx in eax |
shr ecx, 2 |
rep movsd # Copy longwords. |
shld ecx, eax, 2 # Restore excess count |
upword: |
shr ecx, 1 |
rep movsw # Copy words |
adc ecx, ecx # One more byte? |
upbyte: |
rep movsb # Copy bytes |
done: |
mov eax, [ebp+8] # Absolutely noone cares about this value |
pop edi |
pop esi |
pop ebp |
ret |
# Handle bad overlap by copying downwards, don't bother to do word copies. |
downwards: |
std # Set direction bit: downwards |
lea esi, [esi+ecx-1] |
lea edi, [edi+ecx-1] |
rep movsb # Copy bytes |
cld |
jmp done |
/drivers/ddk/string/_strncat.S |
---|
0,0 → 1,43 |
# _strncat() Author: Kees J. Bot |
# 1 Jan 1994 |
# char *_strncat(char *s1, const char *s2, size_t edx) |
# Append string s2 to s1. |
# |
.intel_syntax |
.global __strncat |
.text |
.align 16 |
__strncat: |
push ebp |
mov ebp, esp |
push esi |
push edi |
mov edi, [ebp+8] # String s1 |
mov ecx, -1 |
xorb al, al # Null byte |
cld |
repne |
scasb # Look for the zero byte in s1 |
dec edi # Back one up (and clear 'Z' flag) |
push edi # Save end of s1 |
mov edi, [12+ebp] # edi = string s2 |
mov ecx, edx # Maximum count |
repne |
scasb # Look for the end of s2 |
jne no0 |
inc ecx # Exclude null byte |
no0: sub edx, ecx # Number of bytes in s2 |
mov ecx, edx |
mov esi, [12+ebp] # esi = string s2 |
pop edi # edi = end of string s1 |
rep |
movsb # Copy bytes |
stosb # Add a terminating null |
mov eax, [8+ebp] # Return s1 |
pop edi |
pop esi |
pop ebp |
ret |
/drivers/ddk/string/_strncmp.S |
---|
0,0 → 1,44 |
# strncmp() Author: Kees J. Bot 1 Jan 1994 |
# int strncmp(const char *s1, const char *s2, size_t ecx) |
# Compare two strings. |
# |
.intel_syntax |
.globl __strncmp |
.text |
.align 16 |
__strncmp: |
push ebp |
mov ebp, esp |
push esi |
push edi |
test ecx, ecx # Max length is zero? |
je done |
mov esi, [ebp+8] # esi = string s1 |
mov edi, [ebp+12] # edi = string s2 |
cld |
compare: |
cmpsb # Compare two bytes |
jne done |
cmpb [esi-1], 0 # End of string? |
je done |
dec ecx # Length limit reached? |
jne compare |
done: |
seta al # al = (s1 > s2) |
setb ah # ah = (s1 < s2) |
subb al, ah |
movsx eax, al # eax = (s1 > s2) - (s1 < s2), i.e. -1, 0, 1 |
pop edi |
pop esi |
pop ebp |
ret |
/drivers/ddk/string/_strncpy.S |
---|
0,0 → 1,27 |
# _strncpy() Author: Kees J. Bot |
# 1 Jan 1994 |
# char *_strncpy(char *s1, const char *s2, size_t ecx) |
# Copy string s2 to s1. |
# |
.intel_syntax |
.text |
.globl __strncpy |
.align 16 |
__strncpy: |
mov edi, [ebp+12] # edi = string s2 |
xorb al, al # Look for a zero byte |
mov edx, ecx # Save maximum count |
cld |
repne |
scasb # Look for end of s2 |
sub edx, ecx # Number of bytes in s2 including null |
xchg ecx, edx |
mov esi, [ebp+12] # esi = string s2 |
mov edi, [ebp+8] # edi = string s1 |
rep |
movsb # Copy bytes |
ret |
/drivers/ddk/string/_strnlen.S |
---|
0,0 → 1,30 |
# _strnlen() Author: Kees J. Bot 1 Jan 1994 |
# size_t _strnlen(const char *s, size_t ecx) |
# Return the length of a string. |
.intel_syntax |
.globl __strnlen |
.text |
.align 16 |
__strnlen: |
push ebp |
mov ebp, esp |
push edi |
mov edi, [ebp+8] # edi = string |
xorb al, al # Look for a zero byte |
mov edx, ecx # Save maximum count |
cmpb cl, 1 # 'Z' bit must be clear if ecx = 0 |
cld |
repne |
scasb # Look for zero |
jne no0 |
inc ecx # Don't count zero byte |
no0: |
mov eax, edx |
sub eax, ecx # Compute bytes scanned |
pop edi |
pop ebp |
ret |
/drivers/ddk/string/memcmp.S |
---|
0,0 → 1,59 |
# memcmp() Author: Kees J. Bot |
# 2 Jan 1994 |
# int memcmp(const void *s1, const void *s2, size_t n) |
# Compare two chunks of memory. |
# |
.intel_syntax |
.globl _memcmp |
.text |
.align 16 |
_memcmp: |
cld |
push ebp |
mov ebp, esp |
push esi |
push edi |
mov esi, [8+ebp] # String s1 |
mov edi, [12+ebp] # String s2 |
mov ecx, [16+ebp] # Length |
cmp ecx, 16 |
jb cbyte # Don't bother being smart with short arrays |
mov eax, esi |
or eax, edi |
testb al, 1 |
jnz cbyte # Bit 0 set, use byte compare |
testb al, 2 |
jnz cword # Bit 1 set, use word compare |
clword: shrd eax, ecx, 2 # Save low two bits of ecx in eax |
shr ecx, 2 |
repe |
cmpsd # Compare longwords |
sub esi, 4 |
sub edi, 4 |
inc ecx # Recompare the last longword |
shld ecx, eax, 2 # And any excess bytes |
jmp last |
cword: shrd eax, ecx, 1 # Save low bit of ecx in eax |
shr ecx, 1 |
repe |
cmpsw # Compare words |
sub esi, 2 |
sub edi, 2 |
inc ecx # Recompare the last word |
shld ecx, eax, 1 # And one more byte? |
cbyte: test ecx, ecx # Set 'Z' flag if ecx = 0 |
last: repe |
cmpsb # Look for the first differing byte |
seta al # al = (s1 > s2) |
setb ah # ah = (s1 < s2) |
subb al, ah |
movsxb eax, al # eax = (s1 > s2) - (s1 < s2), i.e. -1, 0, 1 |
mov edx, esi # For bcmp() to play with |
pop edi |
pop esi |
pop ebp |
ret |
/drivers/ddk/string/memcpy.S |
---|
0,0 → 1,26 |
# memcpy() Author: Kees J. Bot 2 Jan 1994 |
# void *memcpy(void *s1, const void *s2, size_t n) |
# Copy a chunk of memory. |
# This routine need not handle overlap, so it does not handle overlap. |
# One could simply call __memmove, the cost of the overlap check is |
# negligible, but you are dealing with a programmer who believes that |
# if anything can go wrong, it should go wrong. |
.intel_syntax |
.globl _memcpy |
.text |
.align 16 |
_memcpy: |
push ebp |
mov ebp, esp |
push esi |
push edi |
mov edi, [ebp+8] # String s1 |
mov esi, [ebp+12] # String s2 |
mov ecx, [ebp+16] # Length |
# No overlap check here |
jmp __memcpy # Call the part of __memmove that copies up |
/drivers/ddk/string/memset.S |
---|
0,0 → 1,47 |
# memset() Author: Kees J. Bot |
# 2 Jan 1994 |
# void *memset(void *s, int c, size_t n) |
# Set a chunk of memory to the same byte value. |
# |
.intel_syntax |
.global _memset |
.text |
.align 16 |
_memset: |
push ebp |
mov ebp, esp |
push edi |
mov edi, [8+ebp] # The string |
movzx eax, byte ptr [12+ebp] # The fill byte |
mov ecx, [16+ebp] # Length |
cld |
cmp ecx, 16 |
jb sbyte # Don't bother being smart with short arrays |
test edi, 1 |
jnz sbyte # Bit 0 set, use byte store |
test edi, 2 |
jnz sword # Bit 1 set, use word store |
slword: |
movb ah, al |
mov edx, eax |
sal edx, 16 |
or eax, edx # One byte to four bytes |
shrd edx, ecx, 2 # Save low two bits of ecx in edx |
shr ecx, 2 |
rep stosd # Store longwords. |
shld ecx, edx, 2 # Restore low two bits |
sword: |
movb ah, al # One byte to two bytes |
shr ecx, 1 |
rep stosw # Store words |
adc ecx, ecx # One more byte? |
sbyte: |
rep stosb # Store bytes |
done: |
mov eax, [8+ebp] # Return some value you have no need for |
pop edi |
pop ebp |
ret |
/drivers/ddk/string/strcat.S |
---|
0,0 → 1,15 |
# strcat() Author: Kees J. Bot |
# 1 Jan 1994 |
# char *strcat(char *s1, const char *s2) |
# Append string s2 to s1. |
# |
.intel_syntax |
.global _strcat |
.text |
.align 16 |
_strcat: |
mov edx, -1 # Unlimited length |
jmp __strncat # Common code |
/drivers/ddk/string/strchr.S |
---|
0,0 → 1,46 |
# strchr() Author: Kees J. Bot 1 Jan 1994 |
# char *strchr(const char *s, int c) |
# Look for a character in a string. |
.intel_syntax |
.globl _strchr |
.text |
.align 16 |
_strchr: |
push ebp |
mov ebp, esp |
push edi |
cld |
mov edi, [ebp+8] # edi = string |
mov edx, 16 # Look at small chunks of the string |
next: |
shl edx, 1 # Chunks become bigger each time |
mov ecx, edx |
xorb al, al # Look for the zero at the end |
repne scasb |
pushf # Remember the flags |
sub ecx, edx |
neg ecx # Some or all of the chunk |
sub edi, ecx # Step back |
movb al, [ebp+12] # The character to look for |
repne scasb |
je found |
popf # Did we find the end of string earlier? |
jne next # No, try again |
xor eax, eax # Return NULL |
pop edi |
pop ebp |
ret |
found: |
pop eax # Get rid of those flags |
lea eax, [edi-1] # Address of byte found |
pop edi |
pop ebp |
ret |
/drivers/ddk/string/strcpy.S |
---|
0,0 → 1,24 |
# strcpy() Author: Kees J. Bot |
# 1 Jan 1994 |
# char *strcpy(char *s1, const char *s2) |
# Copy string s2 to s1. |
# |
.intel_syntax |
.global _strcpy |
.text |
.align 16 |
_strcpy: |
push ebp |
mov ebp, esp |
push esi |
push edi |
mov ecx, -1 # Unlimited length |
call _strncpy # Common code |
mov eax, [8+ebp] # Return s1 |
pop edi |
pop esi |
pop ebp |
ret |
/drivers/ddk/string/strlen.S |
---|
0,0 → 1,15 |
# strlen() Author: Kees J. Bot 1 Jan 1994 |
# size_t strlen(const char *s) |
# Return the length of a string. |
.intel_syntax |
.globl _strlen |
.text |
.align 16 |
_strlen: |
mov ecx, -1 # Unlimited length |
jmp __strnlen # Common code |
/drivers/ddk/string/strncmp.S |
---|
0,0 → 1,15 |
# strncmp() Author: Kees J. Bot 1 Jan 1994 |
# int strncmp(const char *s1, const char *s2, size_t n) |
# Compare two strings. |
# |
.intel_syntax |
.globl _strncmp |
.text |
.align 16 |
_strncmp: |
mov ecx, [esp+12] # Maximum length |
jmp __strncmp # Common code |
/drivers/ddk/string/strncpy.S |
---|
0,0 → 1,28 |
# strncpy() Author: Kees J. Bot |
# 1 Jan 1994 |
# char *strncpy(char *s1, const char *s2, size_t n) |
# Copy string s2 to s1. |
# |
.intel_syntax |
.text |
.globl _strncpy |
.align 16 |
_strncpy: |
push ebp |
mov ebp, esp |
push esi |
push edi |
mov ecx, [ebp+16] # Maximum length |
call __strncpy # Common code |
mov ecx, edx # Number of bytes not copied |
rep |
stosb # strncpy always copies n bytes by null padding |
mov eax, [ebp+8] # Return s1 |
pop edi |
pop esi |
pop ebp |
ret |