%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