ROSE/string.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