strlen
push ebp
mov ebp, esp
push edi; Save nonvolatile register.
push esi; Save nonvolatile register.
mov edi, [ebp+0x8]; Set ESI to the first argument passed in
; aka the pointer to the string.
mov esi, edi; Save original starting point of the string into ESI.
xor al, al; Set AL or the byte being searched for,
; to 0, or a NULL byte.
repne scasb; Keep incrementing EDI and comparing it to see
; if it is a NULL byte. Stop loop when a NULL
; byte is hit.
sub edi, esi; EDI will contain the address of a NULL byte. Subtract
; this address by ESI or the address of the start of the
; string to find the number of bytes read aka the string
; length and save this number in EDI.
mov eax, edi; Return EDI or the string length.
pop esi; Restore original ESI value.
pop edi; Restore original EDI value.
mov esp, ebp; Restore ESP value
pop ebp; Restore frame pointer value
ret; Return
strchr
push ebp
mov ebp, esp; Save ESP value for later restoration. Part of function prologue.
push ebx ; EBX is not a volatile register, so save it onto
; the stack for later restoration. EAX, ECX, and
; EDX are volatile (https://en.wikibooks.org/wiki/X86_Assembly/High-Level_Languages#STDCALL)
mov edx, [ebp+0xC] ; Set EDX to the value of the second
; argument aka int character
mov ebx, [ebp+0x8] ; Set EBX to the value of the first
; argument aka char * str
check_null:
mov ecx, byte ptr [ebx]; Perform a memory read to get the value
; of the current byte in the string.
; Doing this at the top of the loop saves
; us having to do extra memory reads.
cmp ecx, 0 ; Check that we haven't reached the end of the
; string aka the NULL byte.
mov eax, 0 ; Prepare to return 0, aka a
; NULL pointer, as the result.
jz finish ; Jump to finish if the current byte in the string
; is NULL, aka we hit the end of the string.
check_equal:
cmp ecx, edx ; Check if current character in string
; is the one being searched for.
mov eax, ebx ; Set EAX to the location where the character was
; found to set return value correctly.
jz finish ; Jump to finish if the current byte in the
; string is the one being searched for.
loop_jump:
inc ebx ; Increment EBX to point to the
; next character in the string
jmp check_null ; Jump back to the top of the loop to
; continue searching through the string.
finish:
pop ebx ; Restore EBX back to its original value.
mov esp, ebp ; Restore ESP back to its original value.
pop ebp ; Set EBP or the frame pointer, back to its previous value.
ret ; Return
memcpy
push ebp
mov ebp, esp ; Function prologue
push esi ; Save original ESI value, nonvolatile register.
push edi ; Save original EDI value, nonvolatile register.
mov ecx, [ebp+0x10] ; Set ECX to size or the number of bytes to copy over.
mov esi, [ebp+0xC] ; Set ESI to the value of the source argument.
mov edi, [ebp+0x8] ; Set EDI to the value of the destination argument.
cld ; Thanks to zerosum0x0 for pointing out in his articles that
; this needs to be done. Otherwise we can't be sure that EDI
; and ESI will be incremented when doing movsb operation.
rep movsb ; Move ECX number of bytes from ESI, or source to
; EDI, or destination, incrementing EDI and ESI
; with each byte read.
mov eax, [ebp+0x8] ; Set EAX, or the return value, to destination.
pop edi ; Restore original EDI value.
pop esi ; Restore original ESI value.
mov esp, ebp
pop ebp ; Function epilogue
ret
memset
push ebp
mov ebp, esp ; Function prologue
push edi ; Save value of EDI register, nonvolatile register.
mov ecx, [ebp+0x10] ; Set ECX to the argument num
; or number of bytes to set.
mov eax, [ebp+0xC] ; Set EAX to the argument value or
; the value to set the bytes to.
mov edi, [ebp+0x8] ; Set EDI to the argument ptr or the
; address of the block of memory to fill.
cld ; Set the direction flag to 0 to ensure EDI is incremented
; every time the stosb instruction is executed.
rep stosb ; Fill ECX bytes of memory with the value in EAX,
; starting at the address in EDI. EDI will be
; incremented each time the stosb instruction is executed.
mov eax, [ebp+0x8] ; Set the return value to the start of the
; block of memory that was filled out.
pop edi ; Set EDI back to its original value.
mov esp ebp
pop ebp ; Function epilogue
ret;
strset
push ebp ; Save previous frame pointer onto the stack.
mov ebp, esp ; Set EBP to point to the current frame pointer.
mov eax, [ebp+0xC] ; Set EAX to the argument int c
mov ecx, [ebp+0x8]; Set ECX to the argument char * str
loop_start:
cmp byte ptr [ecx], 0 ; Check if the current byte of the
; string being processed is NULL.
jz finish ; Jump to the finish if it is.
mov byte ptr [ecx], al ; Set the current byte in the string
; to the value of the argument c.
inc ecx ; Set ECX to point to the next byte in the string.
jmp loop_start ; Jump back to the start of the loop.
finish:
mov eax, [ebp+8] ; Set the return value to the address of
; the first byte of the string that was set.
mov esp, ebp ; Restore previous ESP value
pop ebp ; Restore previous stack frame value.
ret
strcmp
push ebp
mov ebp, esp ; Function prologue code
push edi ; Save EDI value, nonvolatile register.
push esi ; Save ESI value, nonvolatile register.
mov edx, [ebp+0xC] ; Set EDX to str2
mov ecx, [ebp+0x8] ; Set ECX to str1
dec edx ; Subtract EDX by 1 since the later loop_start code will be
; incrementing it by 1 for each iteration of the loop.
dec ecx ; Subtract ECX by 1 since the later loop_start code will be
; incrementing it by 1 for each iteration of the loop.
loop_start:
inc edx ; Increment EDX to point to the next byte in the str2 string.
inc ecx ; Increment ECX to point to the next byte in the str1 string.
mov edi, byte ptr [edx] ; Set EDI to current byte in str2 being processed.
mov esi, byte ptr [ecx] ; Set ECX to current byte in str1 being processed.
cmp esi, edi ; Compare current byte in str1 to current byte in str2.
jl lower_str1 ; If the value of the current byte being processed
; in str1 is lower than the value of the current
; byte being processed in str2, then jump to lower_str1.
jg greater_str1 ; If the value of the current byte being processed
; in str1 is greater than the value of the current
; byte being processed in str2, then jump to greater_str1.
jmp compare_null ; If the current byte being processed in str1 is
; equal to the current byte being processed in str2,
; then jump to compare_null to see if we the byte
; that was compared is a NULL byte aka we have
; reached the end of both strings.
lower_str1:
mov eax, -1 ; If the first character that does not match has a lower
; value in str1 than str2, return a value < 0. The value
; -1 will work for our purposes.
jmp finish ; Jump to cleanup code.
greater_str1:
mov eax, 1 ; If the first character that does not match has a
; greater value in str1 than str2, return a value
; > 0. The value 1 will work for our purposes.
jmp finish ; Jump to cleanup code.
compare_null:
test edi, edi ; Check that the bytes being currently being processed
; in str1 and str2, which have been determined to be
; the same as one another, are not NULL bytes.
jnz loop_start ; If the bytes that were matched are not NULL
; bytes, continue the processing loop.
mov eax, 0 ; Otherwise if they are both NULL bytes, set the
; return value to 0 to indicate the two strings
; are the same as one another.
finish:
pop esi ; Restore the original value of ESI.
pop edi ; Restore the original value of EDI.
mov esp, ebp
pop ebp ; Function epilogue code
ret