/drivers/ddk/string/_memmove.S |
---|
1,67 → 1,60 |
# _memmove() Author: Kees J. Bot 2 Jan 1994 |
/* _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. |
/* void *_memmove(void *s1, const void *s2, size_t n) */ |
/* Copy a chunk of memory. Handle overlap. */ |
/* */ |
.intel_syntax |
#include "asm.h" |
.globl __memmove, __memcpy |
ENTRY(_memmove) |
push %ebp |
movl %esp, %ebp |
push %esi |
push %edi |
movl 8(%ebp), %edi /* String s1 */ |
movl 12(%ebp), %esi /* String s2 */ |
movl 16(%ebp), %ecx /* Length */ |
movl %edi, %eax |
subl %esi, %eax |
cmpl %ecx, %eax |
jb downwards /* if (s2 - s1) < n then copy downwards */ |
LABEL(_memcpy) |
cld /* Clear direction bit: upwards */ |
cmpl $16, %ecx |
jb upbyte /* Don't bother being smart with short arrays */ |
movl %esi, %eax |
orl %edi, %eax |
testb $1, %al |
jne upbyte /* Bit 0 set, use byte copy */ |
testb $2, %al |
jne upword /* Bit 1 set, use word copy */ |
uplword: |
shrdl $2, %ecx, %eax /* Save low 2 bits of ecx in eax */ |
shrl $2, %ecx |
.text |
rep movsl /* Copy longwords. */ |
shldl $2, %eax, %ecx /* Restore excess count */ |
upword: |
shrl $1, %ecx |
.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? |
rep movsw /* Copy words */ |
adcl %ecx, %ecx /* One more byte? */ |
upbyte: |
rep movsb # Copy bytes |
rep movsb /* Copy bytes */ |
done: |
mov eax, [ebp+8] # Absolutely noone cares about this value |
pop edi |
pop esi |
pop ebp |
movl 8(%ebp), %eax /* 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. |
/* Handle bad overlap by copying downwards, don't bother to do word copies. */ |
downwards: |
std /* Set direction bit: downwards */ |
leal -1(%esi,%ecx,1), %esi |
leal -1(%edi,%ecx,1), %edi |
downwards: |
std # Set direction bit: downwards |
lea esi, [esi+ecx-1] |
lea edi, [edi+ecx-1] |
rep movsb # Copy bytes |
rep movsb /* Copy bytes */ |
cld |
jmp done |
/drivers/ddk/string/_strncat.S |
---|
1,43 → 1,40 |
# _strncat() Author: Kees J. Bot |
# 1 Jan 1994 |
# char *_strncat(char *s1, const char *s2, size_t edx) |
# Append string s2 to s1. |
# |
/* _strncat() Author: Kees J. Bot */ |
/* 1 Jan 1994 */ |
.intel_syntax |
/* char *_strncat(char *s1, const char *s2, size_t edx) */ |
/* Append string s2 to s1. */ |
/* */ |
#include "asm.h" |
.global __strncat |
ENTRY(_strncat) |
push %ebp |
movl %esp, %ebp |
push %esi |
push %edi |
movl 8(%ebp), %edi /* String s1 */ |
movl $-1, %ecx |
xorb %al, %al /* Null byte */ |
cld |
.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 |
repne scasb /* Look for the zero byte in s1 */ |
decl %edi /* Back one up (and clear 'Z' flag) */ |
push %edi /* Save end of s1 */ |
movl 12(%ebp), %edi /* edi = string s2 */ |
movl %edx, %ecx /* 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 |
incl %ecx /* Exclude null byte */ |
no0: |
subl %ecx, %edx /* Number of bytes in s2 */ |
movl %edx, %ecx |
movl 12(%ebp), %esi /* esi = string s2 */ |
pop %edi /* edi = end of string s1 */ |
rep movsb /* Copy bytes */ |
stosb /* Add a terminating null */ |
movl 8(%ebp), %eax /* Return s1 */ |
pop %edi |
pop %esi |
pop %ebp |
ret |
/drivers/ddk/string/_strncmp.S |
---|
1,44 → 1,34 |
# strncmp() Author: Kees J. Bot 1 Jan 1994 |
/* strncmp() Author: Kees J. Bot */ |
/* 1 Jan 1994 */ |
# int strncmp(const char *s1, const char *s2, size_t ecx) |
# Compare two strings. |
# |
/* int strncmp(const char *s1, const char *s2, size_t ecx) */ |
/* Compare two strings. */ |
/* */ |
#include "asm.h" |
.intel_syntax |
.globl __strncmp |
.text |
.align 16 |
__strncmp: |
push ebp |
mov ebp, esp |
push esi |
push edi |
test ecx, ecx # Max length is zero? |
ENTRY(_strncmp) |
push %ebp |
movl %esp, %ebp |
push %esi |
push %edi |
testl %ecx, %ecx /* Max length is zero? */ |
je done |
mov esi, [ebp+8] # esi = string s1 |
mov edi, [ebp+12] # edi = string s2 |
movl 8(%ebp), %esi /* esi = string s1 */ |
movl 12(%ebp), %edi /* edi = string s2 */ |
cld |
compare: |
cmpsb # Compare two bytes |
cmpsb /* Compare two bytes */ |
jne done |
cmpb [esi-1], 0 # End of string? |
cmpb $0, -1(%esi) /* End of string? */ |
je done |
dec ecx # Length limit reached? |
decl %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 |
seta %al /* al = (s1 > s2) */ |
setb %ah /* ah = (s1 < s2) */ |
subb %ah, %al |
movsbl %al, %eax /* eax = (s1 > s2) - (s1 < s2), i.e. -1, 0, 1 */ |
pop %edi |
pop %esi |
pop %ebp |
ret |
/drivers/ddk/string/_strncpy.S |
---|
1,27 → 1,22 |
# _strncpy() Author: Kees J. Bot |
# 1 Jan 1994 |
/* _strncpy() Author: Kees J. Bot */ |
/* 1 Jan 1994 */ |
# char *_strncpy(char *s1, const char *s2, size_t ecx) |
# Copy string s2 to s1. |
# |
/* char *_strncpy(char *s1, const char *s2, size_t ecx) */ |
/* Copy string s2 to s1. */ |
/* */ |
#include "asm.h" |
.intel_syntax |
ENTRY(_strncpy) |
movl 12(%ebp), %edi /* edi = string s2 */ |
xorb %al, %al /* Look for a zero byte */ |
movl %ecx, %edx /* Save maximum count */ |
cld |
.text |
.globl __strncpy |
.align 16 |
repne scasb /* Look for end of s2 */ |
subl %ecx, %edx /* Number of bytes in s2 including null */ |
xchgl %edx, %ecx |
movl 12(%ebp), %esi /* esi = string s2 */ |
movl 8(%ebp), %edi /* edi = string s1 */ |
__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 |
rep movsb /* Copy bytes */ |
ret |
/drivers/ddk/string/_strnlen.S |
---|
1,30 → 1,27 |
# _strnlen() Author: Kees J. Bot 1 Jan 1994 |
/* _strnlen() Author: Kees J. Bot */ |
/* 1 Jan 1994 */ |
# size_t _strnlen(const char *s, size_t ecx) |
# Return the length of a string. |
/* size_t _strnlen(const char *s, size_t ecx) */ |
/* Return the length of a string. */ |
/* */ |
#include "asm.h" |
.intel_syntax |
ENTRY(_strnlen) |
push %ebp |
movl %esp, %ebp |
push %edi |
movl 8(%ebp), %edi /* edi = string */ |
xorb %al, %al /* Look for a zero byte */ |
movl %ecx, %edx /* Save maximum count */ |
cmpb $1, %cl /* 'Z' bit must be clear if ecx = 0 */ |
cld |
.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 |
repne scasb /* Look for zero */ |
jne no0 |
inc ecx # Don't count zero byte |
incl %ecx /* Don't count zero byte */ |
no0: |
mov eax, edx |
sub eax, ecx # Compute bytes scanned |
pop edi |
pop ebp |
movl %edx, %eax |
subl %ecx, %eax /* Compute bytes scanned */ |
pop %edi |
pop %ebp |
ret |
/drivers/ddk/string/asm.h |
---|
0,0 → 1,61 |
/*- |
* Copyright (c) 1990 The Regents of the University of California. |
* All rights reserved. |
* |
* This code is derived from software contributed to Berkeley by |
* William Jolitz. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* 3. Neither the name of the University nor the names of its contributors |
* may be used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
* SUCH DAMAGE. |
* |
* @(#)asm.h 5.5 (Berkeley) 5/7/91 |
*/ |
#ifndef _I386_ASM_H_ |
#define _I386_ASM_H_ |
#define _C_LABEL(x) _ ## x |
#define _ASM_LABEL(x) x |
/* allow overriding entrypoint alignment */ |
#if !defined(_ALIGN_TEXT) |
# define _ALIGN_TEXT .align 16 |
#endif |
#define _ENTRY(x) \ |
.text; _ALIGN_TEXT; .globl x; x: |
#define _LABEL(x) \ |
.globl x; x: |
#define ENTRY(y) _ENTRY(_C_LABEL(y)) |
#define NENTRY(y) _ENTRY(_C_LABEL(y)) |
#define ASENTRY(y) _ENTRY(_ASM_LABEL(y)) |
#define LABEL(y) _LABEL(_C_LABEL(y)) |
#define END(y) .size y, . - y |
#define IMPORT(sym) \ |
.extern _C_LABEL(sym) |
#endif /* !_I386_ASM_H_ */ |
/drivers/ddk/string/bcmp.S |
---|
0,0 → 1,27 |
/* bcmp() Author: Kees J. Bot */ |
/* 2 Jan 1994 */ |
/* int bcmp(const void *s1, const void *s2, size_t n) */ |
/* Compare two chunks of memory. */ |
/* This is a BSD routine that escaped from the kernel. Don't use. */ |
/* (Alas it is not without some use, it reports the number of bytes */ |
/* after the bytes that are equal. So it can't be simply replaced.) */ |
/* */ |
#include "asm.h" |
ENTRY(bcmp) |
push %ebp |
movl %esp, %ebp |
push 16(%ebp) |
push 12(%ebp) |
push 8(%ebp) |
call _C_LABEL(memcmp) /* Let memcmp do the work */ |
testl %eax, %eax |
je equal |
subl 8(%ebp), %edx /* Memcmp was nice enough to leave "esi" in edx */ |
decl %edx /* Number of bytes that are equal */ |
movl 16(%ebp), %eax |
subl %edx, %eax /* Number of bytes that are unequal */ |
equal: |
leave |
ret |
/drivers/ddk/string/bcopy.S |
---|
0,0 → 1,14 |
/* bcopy() Author: Kees J. Bot */ |
/* 2 Jan 1994 */ |
/* void bcopy(const void *s1, void *s2, size_t n) */ |
/* Copy a chunk of memory. Handle overlap. */ |
/* This is a BSD routine that escaped from the kernel. Don't use. */ |
/* */ |
#include "asm.h" |
ENTRY(bcopy) |
movl 4(%esp), %eax /* Exchange string arguments */ |
xchgl 8(%esp), %eax |
movl %eax, 4(%esp) |
jmp _C_LABEL(_memmove) /* Call the proper routine */ |
/drivers/ddk/string/bzero.S |
---|
0,0 → 1,18 |
/* bzero() Author: Kees J. Bot */ |
/* 2 Jan 1994 */ |
/* void bzero(void *s, size_t n) */ |
/* Set a chunk of memory to zero. */ |
/* This is a BSD routine that escaped from the kernel. Don't use. */ |
/* */ |
#include "asm.h" |
ENTRY(bzero) |
push %ebp |
movl %esp, %ebp |
push 12(%ebp) /* Size */ |
push $0 /* Zero */ |
push 8(%ebp) /* String */ |
call _C_LABEL(memset) /* Call the proper routine */ |
leave |
ret |
/drivers/ddk/string/index.S |
---|
0,0 → 1,11 |
/* index() Author: Kees J. Bot */ |
/* 2 Jan 1994 */ |
/* char *index(const char *s, int c) */ |
/* Look for a character in a string. Has suffered from a hostile */ |
/* takeover by strchr(). */ |
/* */ |
#include "asm.h" |
ENTRY(index) |
jmp _C_LABEL(strchr) |
/drivers/ddk/string/memchr.S |
---|
0,0 → 1,29 |
/* memchr() Author: Kees J. Bot */ |
/* 2 Jan 1994 */ |
/* void *memchr(const void *s, int c, size_t n) */ |
/* Look for a character in a chunk of memory. */ |
/* */ |
#include "asm.h" |
ENTRY(memchr) |
push %ebp |
movl %esp, %ebp |
push %edi |
movl 8(%ebp), %edi /* edi = string */ |
movb 12(%ebp), %al /* The character to look for */ |
movl 16(%ebp), %ecx /* Length */ |
cmpb $1, %cl /* 'Z' bit must be clear if ecx = 0 */ |
cld |
repne scasb |
jne failure |
leal -1(%edi), %eax /* Found */ |
pop %edi |
pop %ebp |
ret |
failure: |
xorl %eax, %eax |
pop %edi |
pop %ebp |
ret |
/drivers/ddk/string/memcmp.S |
---|
1,59 → 1,57 |
# memcmp() Author: Kees J. Bot |
# 2 Jan 1994 |
/* memcmp() Author: Kees J. Bot */ |
/* 2 Jan 1994 */ |
# int memcmp(const void *s1, const void *s2, size_t n) |
# Compare two chunks of memory. |
# |
/* int memcmp(const void *s1, const void *s2, size_t n) */ |
/* Compare two chunks of memory. */ |
/* */ |
#include "asm.h" |
.intel_syntax |
ENTRY(memcmp) |
cld |
push %ebp |
movl %esp, %ebp |
push %esi |
push %edi |
movl 8(%ebp), %esi /* String s1 */ |
movl 12(%ebp), %edi /* String s2 */ |
movl 16(%ebp), %ecx /* Length */ |
cmpl $16, %ecx |
jb cbyte /* Don't bother being smart with short arrays */ |
movl %esi, %eax |
orl %edi, %eax |
testb $1, %al |
jne cbyte /* Bit 0 set, use byte compare */ |
testb $2, %al |
jne cword /* Bit 1 set, use word compare */ |
clword: |
shrdl $2, %ecx, %eax /* Save low two bits of ecx in eax */ |
shrl $2, %ecx |
.globl _memcmp |
repe cmpsl /* Compare longwords */ |
subl $4, %esi |
subl $4, %edi |
incl %ecx /* Recompare the last longword */ |
shldl $2, %eax, %ecx /* And any excess bytes */ |
jmp last |
cword: |
shrdl $1, %ecx, %eax /* Save low bit of ecx in eax */ |
shrl $1, %ecx |
.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 |
repe cmpsw /* Compare words */ |
subl $2, %esi |
subl $2, %edi |
incl %ecx /* Recompare the last word */ |
shldl $1, %eax, %ecx /* And one more byte? */ |
cbyte: |
testl %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 %ah, %al |
movsbl %al, %eax /* eax = (s1 > s2) - (s1 < s2), i.e. -1, 0, 1 */ |
movl %esi, %edx /* For bcmp() to play with */ |
pop %edi |
pop %esi |
pop %ebp |
ret |
/drivers/ddk/string/memcpy.S |
---|
1,26 → 1,22 |
# memcpy() Author: Kees J. Bot 2 Jan 1994 |
/* 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. |
/* 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. */ |
/* */ |
#include "asm.h" |
.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 |
ENTRY(memcpy) |
push %ebp |
movl %esp, %ebp |
push %esi |
push %edi |
movl 8(%ebp), %edi /* String s1 */ |
movl 12(%ebp), %esi /* String s2 */ |
movl 16(%ebp), %ecx /* Length */ |
/* No overlap check here */ |
jmp _C_LABEL(_memcpy) /* Call the part of __memmove that copies up */ |
/drivers/ddk/string/memmove.S |
---|
0,0 → 1,10 |
/* 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. */ |
/* */ |
#include "asm.h" |
ENTRY(memmove) |
jmp _C_LABEL(_memmove) /* Call common code */ |
/drivers/ddk/string/memset.S |
---|
1,47 → 1,45 |
# 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. |
# |
/* memset() Author: Kees J. Bot */ |
/* 2 Jan 1994 */ |
.intel_syntax |
/* void *memset(void *s, int c, size_t n) */ |
/* Set a chunk of memory to the same byte value. */ |
/* */ |
#include "asm.h" |
.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 |
ENTRY(memset) |
push %ebp |
movl %esp, %ebp |
push %edi |
movl 8(%ebp), %edi /* The string */ |
movzbl 12(%ebp), %eax /* The fill byte */ |
movl 16(%ebp), %ecx /* 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 |
cmpl $16, %ecx |
jb sbyte /* Don't bother being smart with short arrays */ |
testl $1, %edi |
jne sbyte /* Bit 0 set, use byte store */ |
testl $2, %edi |
jne 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 |
movb %al, %ah |
movl %eax, %edx |
sall $16, %edx |
orl %edx, %eax /* One byte to four bytes */ |
shrdl $2, %ecx, %edx /* Save low two bits of ecx in edx */ |
shrl $2, %ecx |
rep stosl /* Store longwords. */ |
shldl $2, %edx, %ecx /* 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? |
movb %al, %ah /* One byte to two bytes */ |
shrl $1, %ecx |
rep stosw /* Store words */ |
adcl %ecx, %ecx /* One more byte? */ |
sbyte: |
rep stosb # Store bytes |
rep stosb /* Store bytes */ |
done: |
mov eax, [8+ebp] # Return some value you have no need for |
pop edi |
pop ebp |
movl 8(%ebp), %eax /* Return some value you have no need for */ |
pop %edi |
pop %ebp |
ret |
/drivers/ddk/string/rindex.S |
---|
0,0 → 1,11 |
/* rindex() Author: Kees J. Bot */ |
/* 2 Jan 1994 */ |
/* char *rindex(const char *s, int c) */ |
/* Look for the last occurrence a character in a string. Has suffered */ |
/* from a hostile takeover by strrchr(). */ |
/* */ |
#include "asm.h" |
ENTRY(rindex) |
jmp _C_LABEL(strrchr) |
/drivers/ddk/string/strcat.S |
---|
1,15 → 1,11 |
# strcat() Author: Kees J. Bot |
# 1 Jan 1994 |
# char *strcat(char *s1, const char *s2) |
# Append string s2 to s1. |
# |
/* strcat() Author: Kees J. Bot */ |
/* 1 Jan 1994 */ |
.intel_syntax |
/* char *strcat(char *s1, const char *s2) */ |
/* Append string s2 to s1. */ |
/* */ |
#include "asm.h" |
.global _strcat |
.text |
.align 16 |
_strcat: |
mov edx, -1 # Unlimited length |
jmp __strncat # Common code |
ENTRY(strcat) |
movl $-1, %edx /* Unlimited length */ |
jmp _C_LABEL(_strncat) /* Common code */ |
/drivers/ddk/string/strchr.S |
---|
1,46 → 1,41 |
# strchr() Author: Kees J. Bot 1 Jan 1994 |
/* strchr() Author: Kees J. Bot */ |
/* 1 Jan 1994 */ |
# char *strchr(const char *s, int c) |
# Look for a character in a string. |
/* char *strchr(const char *s, int c) */ |
/* Look for a character in a string. */ |
/* */ |
#include "asm.h" |
.intel_syntax |
.globl _strchr |
.text |
.align 16 |
_strchr: |
push ebp |
mov ebp, esp |
push edi |
ENTRY(strchr) |
push %ebp |
movl %esp, %ebp |
push %edi |
cld |
mov edi, [ebp+8] # edi = string |
mov edx, 16 # Look at small chunks of the string |
movl 8(%ebp), %edi /* edi = string */ |
movl $16, %edx /* 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 |
shll $1, %edx /* Chunks become bigger each time */ |
movl %edx, %ecx |
xorb %al, %al /* Look for the zero at the end */ |
repne scasb |
pushf /* Remember the flags */ |
subl %edx, %ecx |
negl %ecx /* Some or all of the chunk */ |
subl %ecx, %edi /* Step back */ |
movb 12(%ebp), %al /* The character to look for */ |
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 |
popf /* Did we find the end of string earlier? */ |
jne next /* No, try again */ |
xorl %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 |
pop %eax /* Get rid of those flags */ |
leal -1(%edi), %eax /* Address of byte found */ |
pop %edi |
pop %ebp |
ret |
/drivers/ddk/string/strcmp.S |
---|
0,0 → 1,11 |
/* strcmp() Author: Kees J. Bot */ |
/* 1 Jan 1994 */ |
/* int strcmp(const char *s1, const char *s2) */ |
/* Compare two strings. */ |
/* */ |
#include "asm.h" |
ENTRY(strcmp) |
movl $-1, %ecx /* Unlimited length */ |
jmp _C_LABEL(_strncmp) /* Common code */ |
/drivers/ddk/string/strcpy.S |
---|
1,24 → 1,20 |
# strcpy() Author: Kees J. Bot |
# 1 Jan 1994 |
# char *strcpy(char *s1, const char *s2) |
# Copy string s2 to s1. |
# |
/* strcpy() Author: Kees J. Bot */ |
/* 1 Jan 1994 */ |
.intel_syntax |
/* char *strcpy(char *s1, const char *s2) */ |
/* Copy string s2 to s1. */ |
/* */ |
#include "asm.h" |
.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 |
ENTRY(strcpy) |
push %ebp |
movl %esp, %ebp |
push %esi |
push %edi |
movl $-1, %ecx /* Unlimited length */ |
call _C_LABEL(_strncpy) /* Common code */ |
movl 8(%ebp), %eax /* Return s1 */ |
pop %edi |
pop %esi |
pop %ebp |
ret |
/drivers/ddk/string/strlen.S |
---|
1,15 → 1,11 |
# strlen() Author: Kees J. Bot 1 Jan 1994 |
/* strlen() Author: Kees J. Bot */ |
/* 1 Jan 1994 */ |
# size_t strlen(const char *s) |
# Return the length of a string. |
/* size_t strlen(const char *s) */ |
/* Return the length of a string. */ |
/* */ |
#include "asm.h" |
.intel_syntax |
.globl _strlen |
.text |
.align 16 |
_strlen: |
mov ecx, -1 # Unlimited length |
jmp __strnlen # Common code |
ENTRY(strlen) |
movl $-1, %ecx /* Unlimited length */ |
jmp _C_LABEL(_strnlen) /* Common code */ |
/drivers/ddk/string/strncat.S |
---|
0,0 → 1,11 |
/* strncat() Author: Kees J. Bot */ |
/* 1 Jan 1994 */ |
/* size_t strncat(char *s1, const char *s2, size_t n) */ |
/* Append string s2 to s1. */ |
/* */ |
#include "asm.h" |
ENTRY(strncat) |
movl 12(%esp), %edx /* Maximum length */ |
jmp _C_LABEL(_strncat) /* Common code */ |
/drivers/ddk/string/strncmp.S |
---|
1,22 → 1,11 |
# strncmp() Author: Kees J. Bot 1 Jan 1994 |
/* strncmp() Author: Kees J. Bot */ |
/* 1 Jan 1994 */ |
# int strncmp(const char *s1, const char *s2, size_t n) |
# Compare two strings. |
# |
/* int strncmp(const char *s1, const char *s2, size_t n) */ |
/* Compare two strings. */ |
/* */ |
#include "asm.h" |
.intel_syntax |
.globl _strncmp |
.globl _strcmp |
.text |
.align 16 |
_strncmp: |
mov ecx, [esp+12] # Maximum length |
jmp __strncmp # Common code |
.align 16 |
_strcmp: |
mov ecx, -1 # Maximum length |
jmp __strncmp # Common code |
ENTRY(strncmp) |
movl 12(%esp), %ecx /* Maximum length */ |
jmp _C_LABEL(_strncmp) /* Common code */ |
/drivers/ddk/string/strncpy.S |
---|
1,28 → 1,23 |
# strncpy() Author: Kees J. Bot |
# 1 Jan 1994 |
# char *strncpy(char *s1, const char *s2, size_t n) |
# Copy string s2 to s1. |
# |
/* strncpy() Author: Kees J. Bot */ |
/* 1 Jan 1994 */ |
.intel_syntax |
/* char *strncpy(char *s1, const char *s2, size_t n) */ |
/* Copy string s2 to s1. */ |
/* */ |
#include "asm.h" |
.text |
ENTRY(strncpy) |
push %ebp |
movl %esp, %ebp |
push %esi |
push %edi |
movl 16(%ebp), %ecx /* Maximum length */ |
call _C_LABEL(_strncpy) /* Common code */ |
movl %edx, %ecx /* Number of bytes not copied */ |
.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 |
rep stosb /* strncpy always copies n bytes by null padding */ |
movl 8(%ebp), %eax /* Return s1 */ |
pop %edi |
pop %esi |
pop %ebp |
ret |
/drivers/ddk/string/strnlen.S |
---|
0,0 → 1,11 |
/* strnlen() Author: Kees J. Bot */ |
/* 1 Jan 1994 */ |
/* size_t strnlen(const char *s, size_t n) */ |
/* Return the length of a string. */ |
/* */ |
#include "asm.h" |
ENTRY(strnlen) |
movl 8(%esp), %ecx /* Maximum length */ |
jmp _C_LABEL(_strnlen) /* Common code */ |
/drivers/ddk/string/strrchr.S |
---|
0,0 → 1,35 |
/* strrchr() Author: Kees J. Bot */ |
/* 2 Jan 1994 */ |
/* char *strrchr(const char *s, int c) */ |
/* Look for the last occurrence a character in a string. */ |
/* */ |
#include "asm.h" |
ENTRY(strrchr) |
push %ebp |
movl %esp, %ebp |
push %edi |
movl 8(%ebp), %edi /* edi = string */ |
movl $-1, %ecx |
xorb %al, %al |
cld |
repne scasb /* Look for the end of the string */ |
notl %ecx /* -1 - ecx = Length of the string + null */ |
decl %edi /* Put edi back on the zero byte */ |
movb 12(%ebp), %al /* The character to look for */ |
std /* Downwards search */ |
repne scasb |
cld /* Direction bit back to default */ |
jne failure |
leal 1(%edi), %eax /* Found it */ |
pop %edi |
pop %ebp |
ret |
failure: |
xorl %eax, %eax /* Not there */ |
pop %edi |
pop %ebp |
ret |