I have the following function which I wrote in NASM to merge two sorted arrays. Its not a standalone, but its supposed to be compiled into a .o
file and then linked to a .c
file from which the function can be called with the following signature:
void merge(int* arr1, int size1, int* arr2, int size2, int* merged_array)
I have tested it and my code works as intended. However, I am somewhat new to assembly and I don't know if I'm following best practices with this code. Also, I timed it against a function that I wrote in C to do the same thing, and the C function consistently outperforms it for large arrays. So I'm wondering if there's any obvious sections of it I can rewrite to improve performance.
global merge
merge: ; entry point for function merge
push ebp
mov ebp, esp
mov eax,[esp+8] ; pointer to array 1
mov esi,[esp+12] ; length of array 1
mov ebx,[esp+16] ; pointer to array 2
mov edi,[esp+20] ; length of array 2
mov edx,[esp+24] ; pointer to destination array (pre-allocated)
begin_merge:
test esi,esi ; if we've run out of array 1
jz copy2 ; just copy over array 2
test edi,edi ; if we've run out of array 2
jz copy1 ; just copy over array 1
;otherwise, compare the first elements
mov ecx,[eax]
cmp ecx,[ebx]
jl merge_from_1 ; if eax > ebx, merge from array 1
jmp merge_from_2; otherwise keep going for the merge from array 2
; merge a single element from an array
merge_from_2:
mov ecx,[ebx]
mov [edx],ecx
add edx,4
add ebx,4
dec edi
jmp begin_merge
merge_from_1:
mov ecx,[eax]
mov [edx],ecx
add edx,4
add eax,4
dec esi
jmp begin_merge
; copy over an entire array
copy1:
test esi,esi ; if we've run out of array 1
jz finish ; end
; otherwise, copy an element from array 1
jmp merge_from_1 ; this will return to begin_merge, but thats okay
; because begin_merge will just forward it on to here again
copy2:
test edi,edi ; if we've run out of array 2
jz finish ; end
; otherwise, copy an element from array 2
jmp merge_from_2 ; this will return to begin_merge, but thats okay
; because begin_merge will just forward it on to here again
finish:
leave
ret