【问题标题】:Assembly (MASM) quickSort装配 (MASM) 快速排序
【发布时间】: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 前面的三个pushret 删除,这三个pop 实际上是在加载旧的ebp,返回地址,以及调用 sortList 之前堆栈中的内容。
  • @Pe7g ENTER 0,0 完成 push ebp mov ebp, espsub esp, numbytes 的工作,然后 LEAVE 弹出 ebp。但是谢谢,我会更多地研究我的堆栈工作
  • @H.W.D 是的,但你在quickSort 过程中没有enter,只有在sortList 中。

标签: assembly masm32


【解决方案1】:

MASM 有响应 PROC 关键字的序言和尾声宏,所以;

quickSort PROC @arr:PTR DWORD, LEFT:DWORD, RIGHT:DWORD

然后汇编器将创建一个可能使用的过程框架

push    ebp
mov     ebp, esp
add     esp, 0xFFF8           for your locals right & left

然后epilogue宏会自动计算传给PROC的字节数并组装

leave
ret     12

同样

mov     esi, [ebp+8]           can be replaced with
mov     esi, [@arr]

我没有 MASM32 来证明我的论点,但我认为它仍然会将 ESP 递减 8 以适应本地人,所以本质上,PROC 的每次迭代,ESP 只会递增 4。可以使用 MASM32没有 PROC,甚至没有混合,但这违背了使用宏的目的。

【讨论】:

    猜你喜欢
    • 2020-08-14
    • 2016-12-23
    • 1970-01-01
    • 1970-01-01
    • 2014-10-10
    • 1970-01-01
    • 2011-07-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多