x86 Assembly Implementations
x86 assembly language implementations covering common patterns, instruction set reference, calling conventions, and translating C to assembly.
Contents
x86 Assembly Implementations
Assumptions: 32-bit x86, stdcall convention, null-terminated C-strings. No prologue/epilogue shown (assume wrapped in proper function). Minimal error handling.
String Length Functions
strlen
Prototype: size_t strlen(const char* str);
Returns: Length excluding null terminator
mov edi, [ebp+8] ; str
xor eax, eax ; AL=0 (search for null)
or ecx, -1 ; max count
repne scasb ; scan until null found
not ecx ; ECX = scanned bytes (len+1)
dec ecx ; exclude null terminator
mov eax, ecx ; return length
strnlen
Prototype: size_t strnlen(const char* str, size_t maxlen);
Returns: Length up to maxlen, excluding null
mov edi, [ebp+8] ; str
mov ecx, [ebp+0Ch] ; maxlen
xor eax, eax ; AL=0
jecxz done ; if maxlen=0, return 0
repne scasb ; scan for null or maxlen reached
jne no_null ; maxlen reached without null
inc ecx ; null found, adjust
no_null:
mov eax, [ebp+0Ch] ; maxlen
sub eax, ecx ; actual length
done:
String Search Functions
strchr
Prototype: char* strchr(const char* str, int ch);
Returns: Pointer to first occurrence of ch, or NULL
mov edi, [ebp+8] ; str
mov al, [ebp+0Ch] ; ch (byte)
or ecx, -1 ; max count
repne scasb ; scan for AL
jne not_found ; no match
lea eax, [edi-1] ; back up to match position
jmp done
not_found:
xor eax, eax ; return NULL
done:
strrchr
Prototype: char* strrchr(const char* str, int ch);
Returns: Pointer to last occurrence of ch, or NULL
mov edi, [ebp+8] ; str
mov dl, [ebp+0Ch] ; ch to find
xor eax, eax ; last found = NULL
scan_loop:
mov cl, [edi] ; current char
test cl, cl ; check for null
jz done ; end of string
cmp cl, dl ; compare with ch
jne next
mov eax, edi ; update last found
next:
inc edi
jmp scan_loop
done:
strstr
Prototype: char* strstr(const char* haystack, const char* needle);
Returns: Pointer to first occurrence of substring, or NULL
mov edi, [ebp+8] ; haystack
mov esi, [ebp+0Ch] ; needle
mov al, [esi] ; first char of needle
test al, al ; empty needle?
jz found_at_start ; return haystack
outer_loop:
mov cl, [edi] ; current haystack char
test cl, cl ; end of haystack?
jz not_found
cmp cl, al ; first char match?
jne next_pos
; Check full substring
push edi
push esi
inc edi
inc esi
inner_loop:
mov dl, [esi] ; needle char
test dl, dl ; end of needle?
jz match_found
cmp dl, [edi] ; compare
jne no_match
inc edi
inc esi
jmp inner_loop
match_found:
pop esi
pop eax ; return start position
jmp done
no_match:
pop esi
pop edi
next_pos:
inc edi
jmp outer_loop
not_found:
xor eax, eax ; return NULL
jmp done
found_at_start:
mov eax, edi ; return haystack
done:
Memory Operations
memcpy
Prototype: void* memcpy(void* dst, const void* src, size_t n);
Returns: dst pointer
mov edi, [ebp+8] ; dst
mov esi, [ebp+0Ch] ; src
mov ecx, [ebp+10h] ; n (byte count)
rep movsb ; copy ECX bytes
mov eax, [ebp+8] ; return dst
memset
Prototype: void* memset(void* dst, int ch, size_t n);
Returns: dst pointer
mov edi, [ebp+8] ; dst
mov al, [ebp+0Ch] ; ch (byte value)
mov ecx, [ebp+10h] ; n (byte count)
rep stosb ; fill ECX bytes with AL
mov eax, [ebp+8] ; return dst
memcmp
Prototype: int memcmp(const void* s1, const void* s2, size_t n);
Returns: 0 if equal, <0 if s1<s2, >0 if s1>s2
mov edi, [ebp+8] ; s1
mov esi, [ebp+0Ch] ; s2
mov ecx, [ebp+10h] ; n
jecxz equal ; n=0, consider equal
repe cmpsb ; compare until mismatch
je equal ; all bytes matched
mov al, [edi-1] ; last byte from s1
sub al, [esi-1] ; difference (s1-s2)
movsx eax, al ; sign extend
jmp done
equal:
xor eax, eax ; return 0
done:
String Comparison
strcmp
Prototype: int strcmp(const char* s1, const char* s2);
Returns: 0 if equal, <0 if s1<s2, >0 if s1>s2
mov edi, [ebp+8] ; s1
mov esi, [ebp+0Ch] ; s2
cmp_loop:
mov al, [edi] ; char from s1
mov dl, [esi] ; char from s2
cmp al, dl ; compare
jne not_equal ; difference found
test al, al ; both null?
jz equal ; yes, strings equal
inc edi
inc esi
jmp cmp_loop
not_equal:
movzx eax, al ; zero-extend s1 char
movzx edx, dl ; zero-extend s2 char
sub eax, edx ; return difference
jmp done
equal:
xor eax, eax ; return 0
done:
strncmp
Prototype: int strncmp(const char* s1, const char* s2, size_t n);
Returns: 0 if equal up to n chars, <0 if s1<s2, >0 if s1>s2
mov edi, [ebp+8] ; s1
mov esi, [ebp+0Ch] ; s2
mov ecx, [ebp+10h] ; n
jecxz equal ; n=0, equal
cmp_loop:
mov al, [edi] ; char from s1
mov dl, [esi] ; char from s2
cmp al, dl ; compare
jne not_equal
test al, al ; null terminator?
jz equal
inc edi
inc esi
loop cmp_loop ; decrement ECX, loop if not zero
equal:
xor eax, eax ; return 0
jmp done
not_equal:
movzx eax, al
movzx edx, dl
sub eax, edx ; return difference
done:
String Copy Functions
strcpy
Prototype: char* strcpy(char* dst, const char* src);
Returns: dst pointer
mov edi, [ebp+8] ; dst
mov esi, [ebp+0Ch] ; src
copy_loop:
lodsb ; load byte from [esi] to AL, inc esi
stosb ; store AL to [edi], inc edi
test al, al ; null terminator?
jnz copy_loop ; continue if not
mov eax, [ebp+8] ; return dst
strncpy
Prototype: char* strncpy(char* dst, const char* src, size_t n);
Returns: dst pointer (may not be null-terminated if src >= n chars)
mov edi, [ebp+8] ; dst
mov esi, [ebp+0Ch] ; src
mov ecx, [ebp+10h] ; n
jecxz done ; if n=0, nothing to copy
copy_loop:
lodsb ; load from src
stosb ; store to dst
test al, al ; was it null?
loopnz copy_loop ; continue if not null and ecx>0
; Pad with nulls if needed
jz pad_nulls
jmp done
pad_nulls:
xor al, al ; AL=0
rep stosb ; fill rest with nulls
done:
mov eax, [ebp+8] ; return dst
String Concatenation
strcat
Prototype: char* strcat(char* dst, const char* src);
Returns: dst pointer
mov edi, [ebp+8] ; dst
mov esi, [ebp+0Ch] ; src
; Find end of dst
xor eax, eax ; search for null
or ecx, -1 ; max count
repne scasb ; find null in dst
dec edi ; back to null position
; Copy src to end
cat_loop:
lodsb ; load from src
stosb ; store to dst
test al, al ; null terminator?
jnz cat_loop
mov eax, [ebp+8] ; return dst
strncat
Prototype: char* strncat(char* dst, const char* src, size_t n);
Returns: dst pointer (always null-terminated)
mov edi, [ebp+8] ; dst
mov esi, [ebp+0Ch] ; src
mov edx, [ebp+10h] ; n
; Find end of dst
xor eax, eax
or ecx, -1
repne scasb
dec edi ; back to null position
; Copy up to n chars
test edx, edx ; n=0?
jz add_null
cat_loop:
lodsb ; load from src
test al, al ; src ended?
jz add_null
stosb ; store to dst
dec edx ; decrement n
jnz cat_loop ; continue if n>0
add_null:
xor al, al ; ensure null terminator
stosb
mov eax, [ebp+8] ; return dst
String Modification
strset
Prototype: char* strset(char* str, int ch);
Returns: str pointer (sets all chars to ch, preserving null)
mov edi, [ebp+8] ; str
mov edx, edi ; save dst pointer
xor eax, eax ; AL=0
or ecx, -1 ; max count
repne scasb ; find null terminator
add ecx, 2
neg ecx ; ECX = string length
mov al, [ebp+0Ch] ; ch (fill character)
mov edi, edx ; reset to start
rep stosb ; fill with ch
mov eax, edx ; return str
strupr
Prototype: char* strupr(char* str);
Returns: str pointer (converts to uppercase)
mov edi, [ebp+8] ; str
mov esi, edi ; save for return
upper_loop:
mov al, [edi] ; load char
test al, al ; null terminator?
jz done
cmp al, 'a' ; less than 'a'?
jb next_char
cmp al, 'z' ; greater than 'z'?
ja next_char
sub al, 32 ; convert to uppercase
mov [edi], al ; store back
next_char:
inc edi
jmp upper_loop
done:
mov eax, esi ; return str
strlwr
Prototype: char* strlwr(char* str);
Returns: str pointer (converts to lowercase)
mov edi, [ebp+8] ; str
mov esi, edi ; save for return
lower_loop:
mov al, [edi] ; load char
test al, al ; null terminator?
jz done
cmp al, 'A' ; less than 'A'?
jb next_char
cmp al, 'Z' ; greater than 'Z'?
ja next_char
add al, 32 ; convert to lowercase
mov [edi], al ; store back
next_char:
inc edi
jmp lower_loop
done:
mov eax, esi ; return str
Notes
- String instructions (REP prefix) use ECX as counter
- Direction flag (DF) assumed clear (0) for forward processing
- SCASB: scan string (compare AL with [EDI]), increment/decrement EDI
- STOSB: store string (AL to [EDI]), increment/decrement EDI
- LODSB: load string ([ESI] to AL), increment/decrement ESI
- MOVSB: move string ([ESI] to [EDI]), increment/decrement both
- CMPSB: compare strings ([ESI] with [EDI]), increment/decrement both