通过平面汇编中的过程对列表进行排序

Sorting a list through a procedure in flat assembly

我是 fasm 的新手,最近才开始学习程序。我的问题是我有一个过程,我希望它以某种方式对我的列表进行排序。但是当我 运行 我的代码时,它似乎只是从内存中对一些随机数进行排序。我不太清楚为什么会这样,如果有任何帮助,我将不胜感激。 这是代码:

format PE gui 5.0
include 'D:\Flat Assembler\INCLUDE\win32a.inc'
entry start

section '.data' data readable writable
    mas1 dw 2, -3, 1, -1, 3, -2, 5, -5, -4, 4

    N = ($ - mas1) / 2
    numStr db N dup('%d  '), 0

    strStr db '%s', 0
    undefStr db 'undefined', 0
    buff db 50 dup(?)
    Caption db 'Result', 0


section '.code' code readable executable
start:

stdcall bubble, mas1

cinvoke wsprintf, buff, numStr
invoke MessageBox, 0, buff, Caption, MB_OK + MB_ICONINFORMATION
invoke ExitProcess, 0


proc bubble, mas:word
    mov ecx, 0
    mov ebx, 0

    outerLoop:
            cmp ecx, 10
            je done
            mov ebx, 2

    innerLoop:
            mov eax, 0
            mov edx, 0

            cmp [mas+ebx], 0 ;if(mas[j] > 0)
            jge continue     ;continue

            mov ax, [mas+ebx-2]

            cmp ax, [mas+ebx]
            jle continue
                mov dx, [mas+ebx]
                mov [mas+ebx-2], dx
                mov [mas+ebx], ax

            continue:
            cmp ebx, 18 ;10
            je innerDone
            add ebx, 2 ;inc ebx
            jmp innerLoop

    innerDone:
            inc ecx
            jmp outerLoop

    done:
    mov ecx, 0
    mov ebx, 0
    mov ebx, 18
    mov ecx, N
    print:
           mov eax, 0
           mov ax, [mas+ebx]
           cwde
           push eax
           sub ebx, 2
           loop print

    ret
    endp

section '.idata' import data readable writeable
    library kernel32,'KERNEL32.DLL',\
            user32,'USER32.DLL'

    include 'D:\Flat Assembler\INCLUDE\API\kernel32.inc'
    include 'D:\Flat Assembler\INCLUDE\API\user32.inc'

错误 1

stdcall bubble, mas1
...
proc bubble, mas:word

参数mas1是地址,作为dword压入栈中。因此,您不应将参数 mas 限制为一个词。
您的 bubble 过程需要的是数组的完整地址。您通过 mov esi, [mas] 获得此信息,FASM 将像您编写 mov esi, [ebp+8] 一样进行编码。当使用标准序言 push ebp mov ebp, esp 时,EBP+8 是第一个参数(在您的程序中是唯一的参数)所在的位置。

错误 2

在您的 bubble 过程中,您将结果数组推入堆栈,希望 wsprintf 从那里使用它,但是一旦 bubble 过程执行它的 ret 指令,结语代码以及 ret 指令本身将开始吃掉你的数组 甚至 return 到错误的地址内存!
如果您要通过堆栈 return 数组,则将其存储在 return 地址和参数 之上。这就是为什么我在下面的程序中写道:

sub esp, N*4                  ; Space for N dwords on the stack
stdcall bubble, mas1

错误 3

cmp [mas+ebx], 0 ;if(mas[j] > 0)
jge continue     ;continue

你的 BubbleSort 是错误的,因为你不允许比较正数!
此外,您进行的迭代次数太多,而且持续时间也太长。


我在 FASM 1.71.22 上测试了以下程序不要忘记更改路径!

format PE gui 5.0
include 'C:\FASM\INCLUDE\win32a.inc'
entry start

section '.data' data readable writable
    mas1 dw 2, -3, 1, -1, 3, -2, 5, -5, -4, 4
    N = ($ - mas1) / 2

    numStr db N-1 dup('%d, '), '%d', 0
    ;strStr db '%s', 0
    ;undefStr db 'undefined', 0
    buff db 50 dup(?)
    Caption db 'Result', 0


section '.code' code readable executable
start:

sub esp, N*4                  ; Space for N dwords on the stack
stdcall bubble, mas1

cinvoke wsprintf, buff, numStr
invoke MessageBox, 0, buff, Caption, MB_OK + MB_ICONINFORMATION
invoke ExitProcess, 0


proc bubble uses ebx esi, mas

    mov   esi, [mas]          ; Address of the array
    mov   ecx, (N-1)*2        ; Offset to the last item; Max (N-1) compares

  outerLoop:
    xor   ebx, ebx

  innerLoop:
    mov   ax, [esi+ebx]
    mov   dx, [esi+ebx+2]
    cmp   ax, dx
    jle   continue
    mov   [esi+ebx+2], ax
    mov   [esi+ebx], dx
  continue:
    add   ebx, 2
    cmp   ebx, ecx
    jb    innerLoop

    sub   ecx, 2
    jnz   outerLoop

    mov   ebx, (N-1)*2
  toStack:
    movsx eax, word [esi+ebx]
    mov   [ebp+12+ebx*2], eax
    sub   ebx, 2
    jnb   toStack

    ret
    endp

section '.idata' import data readable writeable
    library kernel32,'KERNEL32.DLL',\
            user32,'USER32.DLL'

    include 'C:\FASM\INCLUDE\API\kernel32.inc'
    include 'C:\FASM\INCLUDE\API\user32.inc'

重温错误 2

IMO return如果您的 bubble 过程没有修改原始数组,则通过堆栈处理结果数组会更有意义。
但是在你现在的代码中你这样做了,所以...
bubble 过程中点击 toStack 片段后,您可以简单地(在 return 从 bubble 过程)将数组的字大小元素作为双字压入堆栈,然后使用 wsprintf.

  ...

start:
  stdcall bubble, mas1
  mov   ebx, (N-1)*2
toStack:
  movsx eax, word [mas1+ebx]
  push  eax
  sub   ebx, 2
  jnb   toStack
  cinvoke wsprintf, buff, numStr

  ...

  sub   ecx, 2
  jnz   outerLoop
  ; See no more toStack here!
  ret
endp

  ...