Assembly 在汇编语言中实现合并排序
我正试图将合并排序算法从更高级的语言(可能是java?)直接翻译成MASM615。我要翻译的实现如下:Assembly 在汇编语言中实现合并排序,assembly,x86,masm,mergesort,irvine32,Assembly,X86,Masm,Mergesort,Irvine32,我正试图将合并排序算法从更高级的语言(可能是java?)直接翻译成MASM615。我要翻译的实现如下: // sort the subarray arr[i]..arr[j] void mergeSort(int &arr, int i, int j) { if (i == j) return; // terminating condition int m = (i+j)/2; // Step 1: compute the splitting p
// sort the subarray arr[i]..arr[j]
void mergeSort(int &arr, int i, int j)
{
if (i == j) return; // terminating condition
int m = (i+j)/2; // Step 1: compute the splitting point
MergeSort(arr, i, m); // Step 2: sort the left part
MergeSort(arr, m+1, j); // Step 3: sort the right part
Merge(a, i, m, j); // Step 4: merge the sorted parts
}
// merge two subarrays arr[i]..arr[m] and arr[m+1]..arr[j] into a single array
// arr[i]..arr[j]
void merge(int &arr, int i, int m, int j)
{
int l = i; // left pointer
int r = m+1; // right pointer
int k = i; // index in the aux array
while((l <= m) && (r <= j)) // fill out the aux array
{
if (arr[l] < arr[r]) // take the minimum of arr[l] and arr[r]
{
aux[k] = arr[l]; // ... and put it into aux
l++; // update the left pointer
k++; // update the aux pointer
}
else
{
aux[k] = arr[r];
r++; // update the right pointer
k++; // update the aux pointer
}
}
while (l<=m) // put the rest of the left part to aux
{
aux[k] = arr[l];
l++;
k++;
}
while (r<=j) // put the rest of the right part to aux
{
aux[k] = arr[r];
r++;
k++;
}
for (k=i; k<=j; k++) // save the changes in the original array arr
{
arr[k] = aux[k];
}
}
//对子数组arr[i]…arr[j]进行排序
无效合并排序(int&arr、int i、int j)
{
if(i==j)返回;//终止条件
int m=(i+j)/2;//步骤1:计算分割点
MergeSort(arr,i,m);//步骤2:对左侧部分进行排序
MergeSort(arr,m+1,j);//步骤3:对右侧部分进行排序
合并(a,i,m,j);//步骤4:合并已排序的部分
}
//将两个子阵列arr[i]…arr[m]和arr[m+1]…arr[j]合并为一个阵列
//arr[i]…arr[j]
无效合并(int&arr、int i、int m、int j)
{
int l=i;//左指针
int r=m+1;//右指针
int k=i;//辅助数组中的索引
虽然((lI增加了“m”,相当于高级调用“MergeSort(arr,m+1,j);”,但是当我必须执行“Merge(a,I,m,j);”我忘记了这个m实际上是我需要的+1的值。在第二次调用之前,我在代码中再次减小了m,这就解决了它!问题中编写的代码现在是正确的!我只是浏览了一下代码;但我不知道您如何在While2:
之前执行推送操作在我看来,在afterWhileLoops
处的pop
会使堆栈不平衡。的确!让我确保达到了这一点,也许这会解决它。:)我添加了一个新标签“afterWhile1”,并使用它在第一个while循环的终止条件下到达所提到的代码。这一变化可以在我的原始帖子中看到!但是,这显然没有对数组进行排序。运行在:-9、-64、-57、+81、+24…之前和之后得到的当前代码:-2112、-16129、-57、+81、+24。这不仅是顺序,而且是一些值之后的数据不在原始数组中!感谢您发现堆栈不平衡!!!:D在我递增数组索引的方式中出现了一个基本错误,代码在原始帖子中进行了更新,但仍然无法完全工作。看起来,对于DWORD寻址,值被缩放为4与未被缩放之间仍然存在一些不一致4.为了让事情变得更简单,我建议返回到将它们增加1,并且在实际内存访问中只将它们增加4(例如,moveax,[a+l*4]
)。
TITLE MASM Template (main.asm)
INCLUDE Irvine32.inc
.data
info1 BYTE "Array contents before mergeSort procedure:", 0
info2 BYTE "Array contents after mergeSort procedure: ", 0
arr DWORD -9, -64, -57, 81, 24
;, -98, 79, -59, -44, 19
;DWORD 52, -60, -51, -63, 23, -22, -37, 13, 88, 36
arrLen DWORD $ - arr
aux DWORD 5 DUP(0)
;variable definitions
a textequ <esi>
i textequ <eax>
j textequ <ebx>
k textequ <edi>
l textequ <ebp>
m textequ <edx>
r textequ <ecx>
.code
main PROC
;output original array
mov edx, OFFSET info1
call WriteString
call Crlf
call Crlf
push arrLen
push OFFSET arr
call printArr
call Crlf
call Crlf
call Crlf
;call mergeSort
mov eax, arrLen
shr eax, 2
dec eax
push eax
push 0
push OFFSET arr
call mergeSort
mov edx, OFFSET info2
call WriteString
call Crlf
call Crlf
push arrLen
push OFFSET arr
call printArr
ProgEnd:
call Crlf
exit
main ENDP
merge PROC USES eax ebx ecx edx esi edi ebp
;take in params. High level code conversion:
; * i = eax | * &arr = esi
; * m = edx | k = edi
; r = ecx | l = ebp
; * j = ebx
; NOTE: '*' means that the value is passed into the process.
mov a, [esp + 32]
mov i, [esp + 36]
mov m, [esp + 40]
mov j, [esp + 44]
;calculate additional variables: ecx, edi, ebp
mov l, i
mov k, i
mov r, m
inc r
;while loop 1 of 3
While1:
cmp l, m
jg afterWhile1
cmp r, j
jg afterWhile1
;if cond1 && cond2 (need to push pop eax and ebx to compare
;since we are out of general use registers!
push ebx
push eax
mov eax, [a + 4 * l]
mov ebx, [a + 4 * r]
cmp eax, ebx
jge While1_else
;do "if condition success" commands
mov eax, [a + 4 * l]
xchg [aux + 4 * k], eax
inc l
inc k
;restore registers
pop eax
pop ebx
jmp While1
While1_else:
;do "if condition failure" commands
mov eax, [a + 4 * r]
mov [aux + 4 * k], eax
inc r
inc k
;restore registers from above
pop eax
pop ebx
jmp While1
afterWhile1:
;push eax for popping later after BOTH the
;second and third while loop.
push eax
;while loop 2 of 3
While2:
;terminating condition
cmp l, m
jg While3
mov eax, [a + 4 * l]
mov [aux + 4 * k], eax
inc l
inc k
jmp While2
;final While loop
While3:
;terminating condition
cmp r, j
jg afterWhileLoops
mov eax, [a + 4 * r]
mov [aux + 4 * k], eax
inc r
inc k
jmp While3
afterWhileLoops:
;pop eax, since we are done with
;while loops 2 and 3.
pop eax
;set k = i
mov k, i
forLoop1:
;check if k <= j]
cmp k, j
jg endMergeProc
;sacrifice the value of m (edx), since we are
;not using it, nor will need it in the future.
mov m, [aux + 4 * k]
mov [a + 4 * k], m
inc k
jmp forLoop1
endMergeProc:
ret 16
merge ENDP
mergeSort PROC USES eax ebx edx esi
;take in params
mov a, [esp + 20] ;array address
mov i, [esp + 24] ;begin of merge
mov j, [esp + 28] ;end of merge
;return condition: start and end are equal.
cmp i, j
je endMergeSort
;edx = midpoint of eax, ebx
mov m, i
add m, j
shr m, 1
;do recursion part 1.
push m
push i
push a
call mergeSort
;do recursion part 2.
inc m
push j
push m
push a
call mergeSort
;call merge fn (&a, i, m, j)
dec m
push j
push m
push i
push a
call merge
endMergeSort:
ret 12
mergeSort ENDP
printArr PROC USES esi eax ebx ecx
mov esi, [esp + 20] ;array address
mov ecx, [esp + 24] ;array length
xor eax, eax
xor ebx, ebx
printElements:
cmp ebx, ecx
jge endPrintArr
mov eax, [esi + 1 * ebx]
call writeInt
mov al, ' '
call writeChar
add ebx, 4
jmp printElements
endPrintArr:
ret 8
printArr ENDP
END main