通过平面汇编中的过程对列表进行排序
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
...
我是 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
...