【发布时间】:2018-03-04 09:32:49
【问题描述】:
所以我这几天一直在研究这个程序。它似乎只在某些时候有效,其余时间我在 VS 中运行它时会出现堆栈溢出错误。 我的程序在数组中生成 100 到 999 范围内的随机数,其大小由用户输入(最大大小为 200),这就是我声明的数组大小。之后我使用我的 quickSort proc,这里是代码
;-------------------------------------------------------
sortList PROC
; Sets up call to quickSort by calculating size of array,
; then passing high, low, and @array as arugments.
; Receives: @array: PTR DWORD ; reference to array
; req:DWORD ; value of the requested number
; Returns: nothing
;-------------------------------------------------------
enter 0,0
mov eax, [ebp+12] ; value of request
mov ecx, 4 ; size of each element in the array
mul ecx ; multiplied to get sizeof the array
mov ebx, eax ; ebx = size of array
sub ebx, 4 ; sub 4 for starting address last element
mov eax, 0 ; zero eax for beginning element
mov esi, [ebp+8] ; @array
push ebx ; high
push eax ; low
push esi ; @array
call quickSort
pop ebx ; restore ebx
pop eax ; restore eax
pop esi ; restore esi
leave
ret 8
sortList ENDP
;-------------------------------------------------------
quickSort PROC
; Uses recursion to sort the array.
; Receives: @arr: PTR DWORD ; reference to array
; LEFT:DWORD ; value of beg index
; RIGHT:DWORD ; value of end index
; Returns: nothing
; Adapted from: Algorithm implemented in C
; http://www.algolist.net/Algorithms/Sorting/Quicksort
;-------------------------------------------------------
LOCAL right:DWORD, ; high value of array
left:DWORD ; low value of array
mov eax, [ebp+12] ; Value of low into eax
mov left, eax ; left = low
mov ebx, [ebp+16] ; Value of high into ebx
mov right, ebx ; right = high
mov esi, [ebp+8] ; @array
mov edi, [esi] ; edi = pivot
mov eax, left ; eax = i
mov ebx, right ; ebx = j
mainLoop:
cmp eax, ebx ; Loop while i <= j
jg endMain
iCheck:
cmp [esi+eax], edi ; Loop while array[i] > pivot
jle endiCheck
add eax, 4
jmp iCheck
endiCheck:
jCheck:
cmp [esi+ebx], edi ; Loop while array[j] < pivot
jge endjCheck
sub ebx, 4 ; move to array[j-1]
jmp jCheck
endjCheck:
cmp eax, ebx ; If i <= j, swap the places in the array
jg endSwap
; Using stack properties to perform swap
push [esi+eax]
push [esi+ebx]
pop [esi+eax]
pop [esi+ebx]
add eax, 4 ; increment i
sub ebx, 4 ; decrement j
endSwap:
jmp mainLoop
endMain:
mov ecx, right ; restore right index into ecx
mov edx, left ; restore left index into edx
Lrecursion:
cmp edx, ebx ; Compare left to j
jge Rrecursion ; If left < j, then call quickSort again
push ebx ; high value of left half
push edx ; low value of left half
push esi ; @array
call quickSort
Rrecursion:
cmp eax, ecx ; Compare i to right
jge theEnd ; If i < right, call quickSort
push ecx ; high value of right half
push eax ; low value of right half
push esi ; @array
call quickSort
theEnd:
ret 12
quickSort ENDP
在调试器中单步执行断点后,我认为我缺少一个逻辑错误。我输入了三个数组。生成的值是 472 108 988。我的代码正确地放置了 988,但是一旦对最后两个进行排序,它就无法解决。 指向正确方向的指针将不胜感激。我希望我清楚。提前感谢您的任何建议!
【问题讨论】:
-
“它无法解决”究竟是什么意思?为什么
sortList以与推送寄存器相同的顺序弹出寄存器?另外,当Lrecursion下的call quickSort返回时呢?如果Rrecursion下的call quickSort也被调用,您将把 24 个字节压入堆栈,但看起来您只弹出 12 个字节。 -
没有足够远来检查逻辑和算法,但是您使用堆栈的工作在左/右/几乎到处都有缺陷。就像在
quickSort PROC的开头一样,您没有设置ebp,但是您使用它来处理堆栈帧,或者sortList尝试从堆栈中恢复未推送到那里的值等等......我想知道这在测试时如何做一些合理的事情,IMO 它甚至应该无法正常返回。 -
@Michael quickSort 以
ret 12结尾,所以call前面的三个push被ret删除,这三个pop实际上是在加载旧的ebp,返回地址,以及调用sortList之前堆栈中的内容。 -
@Pe7g
ENTER 0,0完成push ebpmov ebp, esp和sub esp, numbytes的工作,然后LEAVE弹出 ebp。但是谢谢,我会更多地研究我的堆栈工作 -
@H.W.D 是的,但你在
quickSort过程中没有enter,只有在sortList中。