2

I'm pretty new to fasm and I just recently started learning about procedures. My problem is that I have a proc and I want it to sort my list in a certain way. But when I run my code it just seems to sort some random numbers from memory. I don't quite know why it happens and I would appreciate any help. Here's the code:

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'
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
alangalt
  • 25
  • 6

1 Answers1

3

Error 1

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

The parameter mas1 is an address and is pushed to the stack as a dword. Therefore you should not limit the argument mas to a word.
What your bubble procedure needs is the full address of the array. You get this via mov esi, [mas] that FASM will encode as if you would have written mov esi, [ebp+8]. EBP+8 is where the first argument (and in your program the only argument) resides, when the standard prologue push ebp mov ebp, esp is used.

Error 2

In your bubble procedure you push the resulting array to the stack hoping to have wsprintf use it from there, but once the bubble procedure executes its ret instruction, the epilogue code as well as the ret instruction itself will start eating your array and even return to the wrong address in memory!
If you're going to return an array via the stack, then store it above the return address and the argument(s). That's why I wrote in my program below:

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

Error 3

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

Your BubbleSort is wrong because you don't allow positive numbers to get compared!
Furthermore you make too many iterations that also continu for too long.


I tested below program on FASM 1.71.22 Don't forget to change the paths!

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'

Error 2 revisited

IMO returning the resulting array through the stack would make better sense if your bubble procedure didn't modify the original array.
But in your present code you do, so...
Once you strike the toStack snippet from the bubble procedure, you can simply (after returning from the bubble procedure) push the word-sized elements of the array to the stack as dwords followed by using 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

  ...
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
  • This was very helpful, thank you. My bubble procedure is not "wrong" however. It needs to skip all the positive numbers so they don't get sorted. That was intentional. Otherwise, great response, thanks a lot. – alangalt Dec 22 '20 at 07:15