I wrote an x86 assembly function using MASM that tests for whether or not an array is continuous. That is to say, if an array with length n that starts with the value k, all the subsequent entries in the array are k+1, k+2, ... k+n.
I am interested in becoming better at x86 and x86-64 assembly and I'm wondering if I could get some feedback on the quality of:
- The algorithm itself
- Comments - am I too thorough? Not thorough enough?
- Label names - are they typically what you would expect handwritten x86 labels to look like?
- The part at the end where I set
eaxin three different cases then jump to a finalpop esi/retinstruction - this felt rather ugly to me, but I couldn't think of a better way to do it
Assembly code:
.386
.MODEL FLAT, C
.CODE
; Checks if an array if integers is continuously increasing.
; I.e. if an array of length n starts with element k, all
; the elements in the array are k, k+1, k+2, k+3... k+n
; Uses:
; ESI - Loop counter (when loop >= length, done looping)
; ECX - Data counter (compare for equality with k, k+1, etc...)
; EDX - Pointer to start of array
; Params:
; ESP+4 - Array pointer
; ESP+8 - Array length
; Because of the PUSH ESI instruction at the start of the function,
; the value relative to ESP increases by 4 when they are accessed
; Returns:
; In EAX:
; 1 - If the array is continuous
; 0 - If the array is not continuous
; -1 - If the function was passed an invalid (<1) length
iscontinuous PROC
; Preserve ESI
push esi
; Check for valid (>=1) length
mov esi, dword ptr [esp+12]
cmp esi, 1
jl invalid_length
; Load data array pointer into EDX and deref into ECX (for first number in data)
mov edx, dword ptr [esp+8]
mov ecx, dword ptr [edx]
; Set EAX as loop counter (start at 0 and keep going till EAX=ESI)
xor eax, eax
continuity_loop:
; Compare array element with current position of counter (pointer to array + offset * sizeof(int))
cmp dword ptr [edx+eax*4], ecx
jne not_continuous
inc ecx
inc eax
cmp eax, esi
jl continuity_loop
; If we reached here without branching into not_continuous, we are good to go; return 1 indicating success
mov eax, 1
jmp end_iscontinuous
not_continuous:
xor eax, eax
jmp end_iscontinuous
invalid_length:
mov eax, -1
end_iscontinuous:
pop esi
ret
iscontinuous ENDP
END
C code for test driver:
#include <stdio.h>
int __cdecl iscontinuous(int *data, int len);
int __cdecl wmain(int argc, wchar_t *argv[])
{
int test[20] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20 };
wprintf_s(L"Test 1 (expected pass): test[0..11] = %d\nTest 2 (expected fail): test[0..20] = %d\nTest 3 (expected pass): test[13..20] = %d\n",
iscontinuous(test, 11),
iscontinuous(test, 20),
iscontinuous(test+12, 7)
);
return 0;
}
Program output:
Test 1 (expected pass): test[0..11] = 1
Test 2 (expected fail): test[0..20] = 0
Test 3 (expected pass): test[13..20] = 1