236 lines
3.1 KiB
NASM
236 lines
3.1 KiB
NASM
; C string.h implementations
|
|
|
|
global memcmp
|
|
global memcpy
|
|
global memset
|
|
global strcmp
|
|
global stpcpy
|
|
global strcpy
|
|
global strlen
|
|
global strncpy
|
|
|
|
; return eax(, edx) parameters stack scratch eax ecx edx preserved ebx esi edi ebp esp
|
|
|
|
; int memcmp(const void s1[], const void s2[], size_t n);
|
|
memcmp:
|
|
mov ecx, [esp+12]
|
|
jecxz .z ; return 0 if n is 0
|
|
push esi
|
|
push edi
|
|
mov esi, [esp+12]
|
|
mov edi, [esp+16]
|
|
mov edx, ecx
|
|
shr ecx, 2
|
|
jz .ld
|
|
repe cmpsd ; find non-matching dwords
|
|
jne .f2
|
|
.ld:
|
|
and edx, 3
|
|
jz .sz ; none left, so all matched
|
|
mov al, byte [esi+0]
|
|
sub al, byte [edi+0]
|
|
jnz .f
|
|
dec edx
|
|
jz .sz
|
|
mov al, byte [esi+1]
|
|
sub al, byte [edi+1]
|
|
jnz .f
|
|
dec edx
|
|
jz .sz
|
|
mov al, byte [esi+2]
|
|
sub al, byte [edi+2]
|
|
jmp .f ; last byte
|
|
.sz: ; no non-matching bytes
|
|
pop edi
|
|
pop esi
|
|
.z:
|
|
xor eax, eax
|
|
ret
|
|
.f: ; diff in al
|
|
movsx eax, al
|
|
pop edi
|
|
pop esi
|
|
ret
|
|
.f2: ; found non-matching dword at ESI-4 <-> EDI-4
|
|
mov eax, [esi-4]
|
|
mov ecx, [edi-4]
|
|
sub al, cl
|
|
jnz .d
|
|
shr eax, 8 ; ESI-3
|
|
shr ecx, 8
|
|
sub al, cl
|
|
jnz .d
|
|
shr eax, 8 ; ESI-2
|
|
shr ecx, 8
|
|
sub al, cl
|
|
jnz .d
|
|
shr eax, 8 ; ESI-1
|
|
shr ecx, 8
|
|
sub al, cl
|
|
.d:
|
|
movsx eax, al
|
|
pop edi
|
|
pop esi
|
|
ret
|
|
|
|
; void *memcpy(void dest[], const void src[], size_t n);
|
|
memcpy:
|
|
mov ecx, [esp+12]
|
|
jecxz .none
|
|
push esi
|
|
push edi
|
|
mov edi, [esp+12]
|
|
mov esi, [esp+16]
|
|
mov edx, ecx
|
|
shr ecx, 2
|
|
jz .dword_done
|
|
rep movsd
|
|
.dword_done:
|
|
test edx, 2
|
|
jz .word_done
|
|
movsw
|
|
.word_done:
|
|
test edx, 1
|
|
jz .done
|
|
movsb
|
|
.done:
|
|
pop edi
|
|
pop esi
|
|
.none:
|
|
mov eax, [esp+4]
|
|
ret
|
|
|
|
; void *memset(void s[], int c, size_t n);
|
|
memset:
|
|
mov ecx, [esp+12]
|
|
jecxz .none
|
|
push edi
|
|
mov edi, [esp+8]
|
|
mov eax, [esp+12]
|
|
mov ah, al
|
|
mov edx, eax
|
|
shl eax, 16
|
|
mov ax, dx
|
|
mov edx, ecx
|
|
shr ecx, 2
|
|
jz .dword_done
|
|
rep stosd
|
|
.dword_done:
|
|
test edx, 2
|
|
jz .word_done
|
|
stosw
|
|
.word_done:
|
|
test edx, 1
|
|
jz .done
|
|
stosb
|
|
.done:
|
|
pop edi
|
|
.none:
|
|
mov eax, [esp+4]
|
|
ret
|
|
|
|
; int strcmp(const char *s1, const char *s2);
|
|
strcmp:
|
|
push esi
|
|
push edi
|
|
mov esi, [esp+12]
|
|
mov edi, [esp+16]
|
|
xor ecx, ecx
|
|
jmp .l_inner
|
|
.l:
|
|
inc ecx
|
|
.l_inner:
|
|
xor eax, eax
|
|
or al, [esi+ecx]
|
|
jz .s1_end
|
|
or ah, [edi+ecx]
|
|
jz .s2_end
|
|
sub al, ah
|
|
jz .l ; equal
|
|
.done:
|
|
movsx eax, al
|
|
pop edi
|
|
pop esi
|
|
ret
|
|
.s1_end:
|
|
mov ah, [edi+ecx]
|
|
.s2_end:
|
|
sub al, ah
|
|
jmp .done
|
|
|
|
; char *stpcpy(char *restrict dst, const char *restrict src);
|
|
stpcpy:
|
|
push esi
|
|
push edi
|
|
mov edi, [esp+12]
|
|
mov esi, [esp+16]
|
|
xor ecx, ecx
|
|
.l:
|
|
xor eax, eax
|
|
or al, [esi+ecx]
|
|
mov [edi+ecx], al
|
|
jz .done
|
|
inc ecx
|
|
jmp .l
|
|
.done:
|
|
lea eax, [edi+ecx]
|
|
pop edi
|
|
pop esi
|
|
ret
|
|
; char *strcpy(char *restrict dst, const char *restrict src);
|
|
strcpy:
|
|
push esi
|
|
push edi
|
|
mov edi, [esp+12]
|
|
mov esi, [esp+16]
|
|
xor ecx, ecx
|
|
.l:
|
|
xor eax, eax
|
|
or al, [esi+ecx]
|
|
mov [edi+ecx], al
|
|
jz .done
|
|
inc ecx
|
|
jmp .l
|
|
.done:
|
|
mov eax, [esp+12]
|
|
pop edi
|
|
pop esi
|
|
ret
|
|
|
|
; size_t strlen(const char *s);
|
|
strlen:
|
|
push edi
|
|
mov edi, [esp+8]
|
|
xor eax, eax
|
|
mov ecx, -1
|
|
repne scasb ; find AL in EDI
|
|
not ecx
|
|
lea eax, [ecx-1]
|
|
pop edi
|
|
ret
|
|
|
|
; char *strncpy(char dst[restrict .dsize], const char *restrict src, size_t dsize);
|
|
strncpy:
|
|
push esi
|
|
push edi
|
|
mov edi, [esp+12]
|
|
mov esi, [esp+16]
|
|
mov ecx, [esp+20]
|
|
jecxz .done
|
|
.l:
|
|
xor eax, eax
|
|
or al, [esi]
|
|
jz .src_empty
|
|
stosb
|
|
inc esi
|
|
loop .l
|
|
jmp .done
|
|
.src_empty:
|
|
rep stosb
|
|
.done:
|
|
mov eax, [esp+12]
|
|
pop edi
|
|
pop esi
|
|
ret
|
|
|