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