アセンブリを使用するプログラムでマージ ソートを実行できるように、このマージ ソート コード (以下を参照) を C++ プログラム (以下も参照) に埋め込みたいと考えています。はい、C++ でマージ ソートを記述できることは承知していますが、代わりにこのアセンブリを埋め込むことが非常に重要です。
マージソートコード:
%include "io.mac"
.DATA
MAX_SIZE EQU 25
%define ARR_LEN dword [n]
PROMPT_ENTER_ARR_LEN db "Enter size of your Array : ", 0
PROMPT_ENTER_ELEMENTS db "Please enter elements of your array : ", 0
print_orig_array db "Original Array ", 0
print_final_array db "Sorted Array ", 0
print_space db " ",0
merge_sort_debug_str db "Merge Sort Params: EAX, ECX: ", 0
merge_sort_end_debug_str db "End Merge Sort", 0
merge_debug_str db "Merge Params: EAX, EBX, ECX, EDX, EDI: ", 0
copy_debug_str db "Copy Params: EAX, EBX, ECX: ", 0
temp_array_debug_str db "Temp array: ", 0
merge_copy_back_temp_debug_str db "Merge Copy back temp array: ", 0
.UDATA
;; Length of the array
n resd 1
;; Array to be sorted
arr resd MAX_SIZE
;; Temporary storage array
temp_arr resd MAX_SIZE
.CODE
.STARTUP
READ_ARR_LEN:
;; Read the length of the array
PutStr PROMPT_ENTER_ARR_LEN
nwln
GetLInt [n] ; Size of input array
PutLInt [n]
nwln
GET_ARRAY:
;; Get values in arr from the user
mov EAX, arr
mov ECX, ARR_LEN
call Read_Arr
;; Print the original array
mov ECX, ARR_LEN
PutStr print_orig_array
call Print_Arr
;; Run Merge Sort on the array
mov EAX, arr
mov EBX, temp_arr
mov ECX, ARR_LEN
call Merge_Sort
;; Print the final array
PutStr print_final_array
call Print_Orig_Arr
.EXIT
Merge_Sort:
;; EAX - Array start
;; ECX - array length
;; Arrays of size 0 or 1 are already sorted
cmp ECX, 2
jl Trivial_Merge_Sort
;; Merge_Sort (first half)
;; Length of the first half
;; ECX /= 2
push ECX
shr ECX, 1
call Merge_Sort
pop ECX
;; Merge_Sort (second half)
push EAX
push EBX
push ECX
;; Length of the second half
;; ECX = ECX - ECX/2
mov EDX, ECX
shr EDX, 1
sub ECX, EDX
imul EDX, 4
;; Start index of the second half
;; EAX = EAX + (ECX/2) * 4
add EAX, EDX
push EDX
call Merge_Sort
pop EDX
pop ECX
pop EBX
pop EAX
pushad
;; Merge (first half, second half)
;; Length of first half = ECX/2
;; Length of second half = ECX - ECX/2
mov EDX, ECX
shr ECX, 1
sub EDX, ECX
;; Start of second half = EAX + (ECX/2) * 4
mov EBX, EAX
mov EDI, ECX
imul EDI, 4
add EBX, EDI
;; Index of temp array = 0
sub EDI, EDI
call Merge
popad
;; Copy back the merged array from temp_arr to arr
call Merge_Copy_Back_Temp
ret
Trivial_Merge_Sort:
;; In case of arrays of length 0 or 1
ret
Merge:
;; Merge two arrays contents.
;; The final merged array will be in temp_arr
;; Merging is done recursively.
;; Arguments:
;; EAX - First array's start
;; EBX - Second array's start
;; ECX - Length of first array
;; EDX - Length of second array
;; EDI - Index in temp array
pushad
;; Handle the cases where one array is empty
cmp ECX, 0
jz First_Array_Over
cmp EDX, 0
jz Second_Array_Over
;; Compare first elements of both the arrays
push EDX
push EDI
mov EDX, [EAX]
mov EDI, [EBX]
cmp EDX, EDI
pop EDI
pop EDX
;; Pick which ever is the least and update that array
jl Update_First_Array
jmp Update_Second_Array
Update_First_Array:
;; min_elem = min (first elements of first array and second array)
;; Put min_elem into the temp array
push dword [EAX]
pop dword [temp_arr + EDI * 4]
add EAX, 4
dec ECX
inc EDI
;; Recursively call Merge on the updated array and the
;; other array
call Merge
popad
ret
Update_Second_Array:
;; min_elem = min (first elements of first array and second array)
;; Put min_elem into the temp array
push dword [EBX]
pop dword [temp_arr + EDI * 4]
add EBX, 4
dec EDX
inc EDI
;; Recursively call Merge on the updated array and the
;; other array
call Merge
popad
ret
Merge_Copy_Back_Temp:
;; Copy back the temp array into original array
;; Arguments:
;; EAX - original array address
;; ECX - original array length
pushad
;; For copying back, the destination array is EAX
mov EBX, EAX
;; Now, the source array is temp_arr
mov EAX, temp_arr
call Copy_Array
popad
ret
Trivial_Merge:
;; Note: One array is empty means no need to merge.
popad
ret
First_Array_Over:
;; Copy the rest of the second array to the temp arr
;; because the first array is empty
pushad
mov EAX, EBX
mov ECX, EDX
mov EBX, temp_arr
imul EDI, 4
add EBX, EDI
call Copy_Array
popad
popad
ret
Second_Array_Over:
;; Copy the rest of the first array to the temp arr
;; because the second array is empty
pushad
mov EBX, temp_arr
imul EDI, 4
add EBX, EDI
call Copy_Array
popad
popad
ret
Copy_Array:
;; Copy array to destination array
;; EAX - Array start
;; EBX - Destination array
;; ECX - Array length
;; Trivial case
cmp ECX, 0
jz Copy_Empty_Array
push ECX
sub EDI, EDI
copy_loop:
;; Copy each element
push dword [EAX + EDI * 4]
pop dword [EBX + EDI * 4]
inc EDI
loop copy_loop
pop ECX
ret
Copy_Empty_Array:
ret
Read_Arr:
;; EAX - array start
;; ECX - array length
PutStr PROMPT_ENTER_ELEMENTS
nwln
mov ESI, EAX
sub EDI, EDI
loop1:
;; Read each element
GetLInt [ESI + EDI * 4]
inc EDI
loop loop1
ret
Print_Temp_Arr:
;; Print contents of temp_arr (for debugging)
pushad
mov EAX, temp_arr
mov ECX, ARR_LEN
call Print_Arr
popad
ret
Print_Orig_Arr:
;; Print contents of arr (for debugging)
pushad
mov EAX, arr
mov ECX, ARR_LEN
call Print_Arr
popad
ret
Print_Arr:
;; Print contents of an array
;; EAX - Array start
;; ECX - array length
nwln
mov ESI, EAX
sub EDI, EDI
new_loop1:
PutLInt [ESI + EDI * 4]
PutStr print_space
inc EDI
loop new_loop1
nwln
ret
C++ コード:
#include <iostream>
#include <cmath>
#include <stdio.h>
using namespace std;
int main()
{
//insert assembly code here
return 0;
}