219 lines
4.5 KiB
NASM
219 lines
4.5 KiB
NASM
%include "src/constants.asm"
|
|
|
|
section .text
|
|
global strlen
|
|
global strcpy
|
|
global strcat
|
|
global strclr
|
|
global strcmp
|
|
global strfind
|
|
|
|
;----- strlen(*str[]) -----;
|
|
; Gets the length of given string
|
|
; Return value: Length of given string
|
|
; Used registers:
|
|
; rax* Byte to check in str[] >> (ret) length of given string
|
|
; rdi* (arg) Pointer to str[]
|
|
; rcx* Counter for scasb
|
|
strlen:
|
|
xor al, al
|
|
mov rcx, -1
|
|
cld
|
|
repne scasb
|
|
mov rax, rcx
|
|
not rax
|
|
dec rax
|
|
ret
|
|
|
|
;----- strcpy(*dest[], *src[], maxLength) -----;
|
|
; Copies one string (src) into the other (dest), overwriting dest
|
|
; NOTE: maxLength must never exceed size of dest[].
|
|
; Return value: Pointer to dest[]
|
|
; Used registers:
|
|
; rax* (ret) Pointer to dest[]
|
|
; rdi* (arg) Pointer to dest[]
|
|
; rsi* (arg) Pointer to src[]
|
|
; rdx (arg) Size of dest[]
|
|
; rcx* Counter for movsb
|
|
; r8* Backup for rdi
|
|
strcpy:
|
|
mov r8, rdi
|
|
mov rdi, rsi
|
|
call strlen
|
|
inc rax
|
|
cmp rax, rdx
|
|
cmova rcx, rdx
|
|
cmovbe rcx, rax
|
|
cmp rcx, rdx
|
|
jb .copy
|
|
dec rcx
|
|
.copy:
|
|
mov rdi, r8
|
|
cld
|
|
rep movsb
|
|
mov byte [rdi], EOS
|
|
mov rax, r8
|
|
ret
|
|
|
|
;----- strcat(*dest[], *src[], maxLength) -----;
|
|
; Concatenate src[] into dest[]
|
|
; Return value: Pointer to dest[]
|
|
; Used registers:
|
|
; rax* (ret) Pointer to dest[]
|
|
; rdi* (arg) Pointer to dest[]
|
|
; rsi* (arg) Pointer to src[]
|
|
; rdx (arg) Size of dest[]
|
|
; rcx* Counter for movsb
|
|
; r8* Backup for rdi (point to start of dest)
|
|
; r9* Backup for rsi
|
|
; r10* Backup for rdi (point to end of dest)
|
|
; r11* Backup for strlen(dest)
|
|
strcat:
|
|
mov r8, rdi
|
|
mov r9, rsi
|
|
call strlen
|
|
mov r11, rax
|
|
sub rdx, rax
|
|
dec rdi
|
|
mov r10, rdi
|
|
mov rdi, rsi
|
|
call strlen
|
|
cmp rax, rdx
|
|
jb .copy
|
|
dec rdx
|
|
|
|
.copy:
|
|
cmp rdx, r11
|
|
jle .quit
|
|
mov rcx, rdx
|
|
mov rsi, r9
|
|
mov rdi, r10
|
|
cld
|
|
rep movsb
|
|
mov byte [rdi], EOS
|
|
.quit:
|
|
mov rax, r8
|
|
ret
|
|
|
|
;----- strclr(*str[], maxLength) -----;
|
|
; Clears a string by placing [maxLength] EOS into string.
|
|
; Thus DANGEROUS function: MAKE SURE maxLength IS SIZE OF str[] - greater values WILL cause issues and eventually crashes
|
|
; Return value: N/A
|
|
; Used registers:
|
|
; rdi* (arg) Pointer to str[]
|
|
; rsi (arg) Length of str[]
|
|
; rcx* Counter for STOSB
|
|
; rax* Character storage (AL) for STOSB
|
|
strclr:
|
|
mov rcx, rsi
|
|
xor al, al
|
|
cld
|
|
rep stosb
|
|
ret
|
|
|
|
;----- strcmp(*str1[], *str2[]) -----;
|
|
; Compares str2 against str1
|
|
; Return values:
|
|
; 0 Two strings are the same, OR str1 or str2 is empty
|
|
; Length of str1 str2 is longer than str1, but no difference was found in between str1 and str2 -up to the point str1 ended-
|
|
; Anything else Position (index+1) where str1 and str2 differ
|
|
; Used registers:
|
|
; rax* (ret)
|
|
; rdi Pointer to str1
|
|
; rsi Pointer to str2
|
|
; rcx* Counter for scasb
|
|
; rdx* Length of str1
|
|
; r8* Backup for rdi
|
|
strcmp:
|
|
xor rax, rax
|
|
cmp byte [rdi], EOS
|
|
je .equal
|
|
cmp byte [rsi], EOS
|
|
je .equal
|
|
|
|
mov r8, rdi
|
|
call strlen
|
|
mov rcx, rax
|
|
mov rdx, rax
|
|
mov rdi, r8
|
|
cld
|
|
repe cmpsb
|
|
je .equal
|
|
mov rax, rdx
|
|
sub rax, rcx
|
|
jmp .quit
|
|
|
|
.equal:
|
|
cmp byte [rsi], EOS
|
|
jne .quit
|
|
xor rax, rax
|
|
|
|
.quit:
|
|
ret
|
|
|
|
;----- strfind(*str[], *what[], start_at) -----;
|
|
; Finds string inside another string.
|
|
; Return values: 0 if what[] wasn't found within str[]. Position (index+1) where first character was found in str[] otherwise
|
|
; Used registers:
|
|
; rax* (ret)
|
|
; rdi (arg) Pointer to str[]
|
|
; rsi (arg) Pointer to what[]
|
|
; rdx (arg) Where to start looking in str[] (index)
|
|
; rcx* Keeps track of current position in str[]
|
|
; r8* Stores index where first character match of what[] was found
|
|
; r9* Used to move byte for cmp instruction
|
|
; r10* Keeps track if there is currently a match between str[] and what[]
|
|
; r11* Backup for original pointer to what[]
|
|
strfind:
|
|
xor rax, rax
|
|
mov rcx, 1
|
|
add rcx, rdx
|
|
add rdi, rdx
|
|
xor r10b, r10b
|
|
mov r11, rsi
|
|
.findStr:
|
|
cmp byte [rsi], EOS
|
|
je .testFullMatch
|
|
cmp byte [rdi], EOS
|
|
je .quit
|
|
|
|
mov r9b, byte [rsi]
|
|
cmp byte [rdi], r9b
|
|
jne .noMatch
|
|
|
|
;.hasMatch:
|
|
test r10b, r10b
|
|
jnz .notFirstChar
|
|
mov r10b, 1
|
|
mov r8, rcx
|
|
.notFirstChar:
|
|
inc rsi
|
|
jmp .continueLoop
|
|
|
|
.noMatch:
|
|
; not gonna figure out here if there was an existing match already. just XOR r10b,r10b and load original pointer to what[] to rsi
|
|
; EDIT: actually yes I am. strfind("gidgiddy", "giddy", 0); [gid]giddy<>[gid]dy is a match but then gid[g]iddy<>gid[d]y is not while it should check gid[g]iddy<>[g]iddy
|
|
test r10b, r10b
|
|
jz .continueLoop
|
|
mov rsi, r11
|
|
mov r9b, byte [rsi]
|
|
cmp byte [rdi], r9b
|
|
jne .itReallyWasNoMatchAfterAll
|
|
mov r8, rcx
|
|
inc rsi
|
|
jmp .continueLoop
|
|
.itReallyWasNoMatchAfterAll:
|
|
xor r10b, r10b
|
|
mov rsi, r11
|
|
|
|
.continueLoop:
|
|
inc rdi
|
|
inc rcx
|
|
jmp .findStr
|
|
.testFullMatch:
|
|
test r10b, r10b
|
|
jz .quit
|
|
mov rax, r8
|
|
.quit:
|
|
ret
|