flat assembler
Message board for the users of flat assembler.

Index > Windows > Adressing Data Problem

Author
Thread Post new topic Reply to topic
Killerkarnickel



Joined: 04 May 2010
Posts: 7
Killerkarnickel
Hello Guys,

I'am new to fasm, so please forgive me my foolish question.
I would like to implement Bubblesort in my little Program. File/Console IO works great. But I'am too stupid for the Bubblesort. Could someone help me?

'SortMe.txt'
Code:
9
6
0
8
5
2
4
3
1
7    

'BUBBLESORT.ASM'
Code:
include 'win32ax.inc'

.data
        fileName              db      'SortMe.txt',0
        fileNameSave          db      'SortMe_sorted.txt',0
        fHandle               dd      0
        fSize                 dd      0
        fBuffer               dd      0
        fBytesRead            dd      0
        tString               db      'Hello World!',0
        numberOfBytesWritten  rd      1
        separator             db      13, 10
        sizeof.separator = $ - separator

.code

main:
        invoke  AllocConsole
        invoke  WriteConsole,<invoke GetStdHandle,STD_OUTPUT_HANDLE>,'Input:',5,numberOfBytesWritten,0
        invoke  WriteConsole,<invoke GetStdHandle,STD_OUTPUT_HANDLE>,separator,sizeof.separator,numberOfBytesWritten,0

        ;Read FileContent
        invoke CreateFile, fileName, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0
        mov [fHandle], eax
        invoke GetFileSize, [fHandle], 0
        mov [fSize], eax
        invoke GlobalAlloc, GMEM_FIXED, [fSize]
        mov    [fBuffer], eax
        invoke ReadFile, [fHandle], [fBuffer], [fSize], fBytesRead,0

        ;Print FileContent
        ;invoke  WriteConsole,<invoke GetStdHandle,STD_OUTPUT_HANDLE>,tString,12,0,0
        invoke  WriteConsole,<invoke GetStdHandle,STD_OUTPUT_HANDLE>,[fBuffer],[fSize],numberOfBytesWritten,0
        invoke  WriteConsole,<invoke GetStdHandle,STD_OUTPUT_HANDLE>,separator,sizeof.separator,numberOfBytesWritten,0
        invoke  WriteConsole,<invoke GetStdHandle,STD_OUTPUT_HANDLE>,'Output:',7,numberOfBytesWritten,0
        invoke  WriteConsole,<invoke GetStdHandle,STD_OUTPUT_HANDLE>,separator,sizeof.separator,numberOfBytesWritten,0

        stdcall bubble_sort,fBuffer,fSize

        ;Save FileContent
        invoke CreateFile,'SortMe_sorted.txt', GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0
        mov [fHandle], eax
        invoke WriteFile, [fHandle], [fBuffer],[fSize], numberOfBytesWritten, 0
        invoke CloseHandle, [fHandle]

        ;invoke  WriteConsole,<invoke GetStdHandle,STD_OUTPUT_HANDLE>,[fBuffer],[fSize],numberOfBytesWritten,0

        invoke  Sleep, -1
.end main

proc bubble_sort buffer:DWORD, count:DWORD
        push ebx
        push esi

        mov esi, [buffer]
        mov ebx, [count]

        mov eax, [esi]
        mov ecx, [esi+4]

        invoke  WriteConsole,<invoke GetStdHandle,STD_OUTPUT_HANDLE>,eax,1,numberOfBytesWritten,0

        pop esi
        pop ebx

        ret
endp
    


You only have to tell me how I can swap two entries in my fBuffer.
Writing eax to console works well. But ecx doesn't.

Here is another post with some bubblesort code:
http://board.flatassembler.net/topic.php?t=3048

Thanks in advance!


Last edited by Killerkarnickel on 10 May 2010, 09:07; edited 1 time in total
Post 10 May 2010, 08:40
View user's profile Send private message Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr
Killerkarnickel,

Do you really need GUI application with console? Use format PE console before include 'win32ax.inc' and forget about AllocConsole().

Usually the swap(a,b) is done like this:
  1. copy a to temporary location;
  2. copy b to a;
  3. copy temporary location to b;
I don't see any conversion there, are you going to sort strings? Then it's easier to manipulate pointers than strings themselves.

To concentrate on bubblesort and not I/O you may use some standard library for latter. For example, 'Input:' string is 6 bytes long (not counting NUL terminator), not 5 as you specified in WriteConsole() call. If you want to include CR/LF in string for invoke, use <'Input', 13, 10>.
Post 10 May 2010, 09:06
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1901
DOS386
What's the exact content of the file ? Just ASCII digits ? Or every digit followed by CR and LF ?

What's the size of your elements ? 1 Byte ? 3 Byte's ?

Code:
    MOV AL, [ESI]
    MOV CL, [ESI+1] ; Should be bigger or equal
    CMP CL, AL
    JAE @f
    MOV [ESI], CL
    MOV [ESI+1],AL
@@: NOPE
    


And YES, better brew a pure console app Wink

I'm not going to comment on your WriteConsole usage, I didn't test your code and I'm using other style Neutral


Last edited by DOS386 on 10 May 2010, 09:16; edited 1 time in total
Post 10 May 2010, 09:14
View user's profile Send private message Reply with quote
Killerkarnickel



Joined: 04 May 2010
Posts: 7
Killerkarnickel
@baldr
No I don't need a GUI for that. Now I changed everything you mentioned.
I want to sort numbers first.

But I don't know how I can address each of the numbers in my string.

Edit: @DOS386

ASCII Digits followed by CR/LF.
Post 10 May 2010, 09:16
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1901
DOS386
Again, size of the elements is crucial. Hint: Start with fixed size of 1 Byte or 4 Byte's Wink Variable size is also doable considering we always swap 2 neighbor elements only in BubbleSortEx algo Wink

EDIT: then your element size is 3 Byte's (doable but not good)
Post 10 May 2010, 09:19
View user's profile Send private message Reply with quote
Killerkarnickel



Joined: 04 May 2010
Posts: 7
Killerkarnickel
Ok, now I have "9608524317" in my File. 10 Bytes in a row. But I'am still not able to swap two values...
Post 10 May 2010, 09:37
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1901
DOS386
Killerkarnickel wrote:
Ok, now I have "9608524317" in my File. 10 Bytes in a row. But I'am still not able to swap two values...


Good, element size is 1 Byte, just use my code. Make sure not to access outside buffer (9 comparisons per pass) and check when done:

Code:
    MOV AH, 0 ; ASS'ume: done

...

    MOV AL, [ESI] 
    MOV CL, [ESI+1] ; Should be bigger or equal 
    CMP CL, AL 
    JAE @f ; Good
    MOV AH,1 ; Heh: NOT done
    MOV [ESI], CL 
    MOV [ESI+1],AL 
@@: NOPE
    
Post 10 May 2010, 09:45
View user's profile Send private message Reply with quote
Killerkarnickel



Joined: 04 May 2010
Posts: 7
Killerkarnickel
My proc "bubble_sort" looks like that:
Code:
proc bubble_sort buffer:DWORD, count:DWORD
        push ebx
        push esi

        mov esi, [buffer]
        mov ebx, [count]

        MOV AH, 0 ; ASS'ume: done 

        MOV AL, [ESI]
        MOV CL, [ESI+1] ; Should be bigger or equal
        CMP CL, AL
        JAE jumphere ; Good
        MOV AH,1 ; Heh: NOT done
        MOV [ESI], CL
        MOV [ESI+1],AL
jumphere:

        ;invoke  WriteConsole,<invoke GetStdHandle,STD_OUTPUT_HANDLE>,eax,1,numberOfBytesWritten,0

        pop esi
        pop ebx

        ret
endp    


Output stays empty with that code. The @f, @@ does not work. Is "NOPE" a instruction?
Post 10 May 2010, 09:56
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1901
DOS386
You need the inner loop (walking through the 9+1 elements) and the outer loop (running until a pass ends with no change (AH=0)).

> The @f, @@ does not work.

Strange Confused

> Is "NOPE" a instruction?

Use with care (nobody said my code would be 100% complete).

Also, you will report the buffer when sorting is done, and make sure to point to the buffer and have the size (10) correct.
Post 10 May 2010, 10:00
View user's profile Send private message Reply with quote
Killerkarnickel



Joined: 04 May 2010
Posts: 7
Killerkarnickel
Code:
proc bubble_sort buffer:DWORD, count:DWORD
        push ebx
        push esi

        sub [count], 1              ; set count to 1 less than member count

lbl0:
        mov esi, [buffer]           ; load array address into ESI
        xor edx, edx                ; zero the "changed" flag
        mov ebx, 10                 ; set the loop counter to member count

lbl1:
        mov eax, [esi]              ; load first pair of array numbers into registers
        mov ecx, [esi+1]
        cmp eax, ecx                ; compare which is higher
        jl lbl2

        mov [esi], ecx              ; swap if 1st number is higher
        mov [esi+4], eax
        mov edx, 1                  ; set the changed flag if any swap is performed

lbl2:
        add esi, 4                  ; step up one to compare next adjoining pair
        sub ebx, 1                  ; decrement the counter
        jnz lbl1

        test edx, edx               ; test if the changed flag is set.
        jnz lbl0                    ; loop back if it is

        pop esi
        pop ebx

        ret
endp    

That's how I would implement Bubblesort.
With that Code I get the same output as input.

[count] does not contain the number 9.
And I don't know how I finally should get my code running.
Post 10 May 2010, 10:38
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1901
DOS386
> sub [count], 1 ; set count to 1 less than member count
> mov ebx, 10 ; set the loop counter to member count

???

> mov [esi+4], eax
> add esi, 4 ; step up one to compare next adjoining pair
> cmp eax, ecx ; compare which is higher

Didn't we say that element size is 1 Byte ???

> [count] does not contain the number 9.

Then you have a problem when reading the source file, it must return 10 into your [count].
Post 10 May 2010, 10:43
View user's profile Send private message Reply with quote
Killerkarnickel



Joined: 04 May 2010
Posts: 7
Killerkarnickel
Of course we said element size is 1 Byte ... but it does not work with 1 Byte.
I tried some values and only with the above ones it has an output.

Here is an working MASM Example:

Code:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

comment * -----------------------------------------------------
                        Build this  template with
                       "CONSOLE ASSEMBLE AND LINK"
        ----------------------------------------------------- *

    bubble_sort PROTO :DWORD,:DWORD

    printarr MACRO parr,cnt
      LOCAL lbl
      push ebx
      push esi
      mov esi, parr
      mov ebx, cnt
    lbl:
      print str$([esi]),13,10
      add esi, 4
      sub ebx, 1
      jnz lbl
      pop esi
      pop ebx
    ENDM

    .data?
      value dd ?

    .data
      narr dd 1,9,2,8,3,7,4,6,5,0   ; 10 unsorted numbers

    .code

start:
   
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    call main
    inkey
    exit

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

main proc

    print "Unsorted",13,10

    printarr OFFSET narr,LENGTHOF narr

    invoke bubble_sort,OFFSET narr,LENGTHOF narr

    print chr$(13,10)
    print "Sorted",13,10

    printarr OFFSET narr,LENGTHOF narr

    ret

main endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

bubble_sort proc parr:DWORD,cnt:DWORD

    push ebx
    push esi

    sub cnt, 1                  ; set count to 1 less than member count

  lbl0:
    mov esi, parr               ; load array address into ESI
    xor edx, edx                ; zero the "changed" flag
    mov ebx, cnt                ; set the loop counter to member count

  lbl1:
    mov eax, [esi]              ; load first pair of array numbers into registers
    mov ecx, [esi+4]
    cmp eax, ecx                ; compare which is higher
    jl lbl2                     

    mov [esi], ecx              ; swap if 1st number is higher
    mov [esi+4], eax
    mov edx, 1                  ; set the changed flag if any swap is performed

  lbl2:
    add esi, 4                  ; step up one to compare next adjoining pair
    sub ebx, 1                  ; decrement the counter
    jnz lbl1

    test edx, edx               ; test if the changed flag is set.
    jnz lbl0                    ; loop back if it is

    pop esi
    pop ebx

    ret

bubble_sort endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

end start
    
Post 10 May 2010, 10:51
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1901
DOS386
> Here is an working MASM Example:
> print str$([esi]),13,10

BAYSIC ??? Laughing

> narr dd 1,9,2,8,3,7,4,6,5,0 ; 10 unsorted numbers

dd is 4 Byte's Wink
Post 10 May 2010, 11:19
View user's profile Send private message Reply with quote
Killerkarnickel



Joined: 04 May 2010
Posts: 7
Killerkarnickel
That MASM example is in included in the standard installation. I don't like the MASM ... that's why I use FASM Wink

I tried to convert this example to fasm ... you see my result above. I switched to

Code:
mov [esi+1], eax
...
add esi, 1    


now. And got an infinite loop.
Code:
#test edx, edx ;this flag is set every round    


But back to my first Question:

why does
Code:
#mov esi, [buffer]
#mov eax, [esi]
#invoke  WriteConsole, handle, eax, 1, ,
    

work. And
Code:
#mov esi, [buffer]
#mov eax, [esi+i]          ; i=1,...n
#invoke  WriteConsole, handle, eax, 1, ,
    

does not.
Post 10 May 2010, 11:23
View user's profile Send private message Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr
Killerkarnickel,

Second WriteConsole() argument is an address of buffer with characters to output, how can it work? mov eax,[esi+i] puts four bytes from esi+i into eax, then WriteConsole() use this as a pointer to the data for output. Confused Is there any data at 0x33323130 (or 0x38303639 if sort didn't work)?
Code:
        format  PE console
        include "Win32AX.Inc"

        .code
sort:
        mov     esi, buffer
        lodsb
        .repeat
          mov     ah, al
          lodsb
          .if al<ah
            mov     [esi-2], ax
            jmp     sort
          .endif
        .until esi>=buffer.end
        invoke  WriteFile, STD_OUTPUT_HANDLE, buffer, buffer.end-buffer, esp, 0
        ret

        .data
buffer  db      "9608524317"
buffer.end:

        .end    sort    
This implementation is made unoptimal for simplicity.
Post 10 May 2010, 14:46
View user's profile Send private message Reply with quote
edemko



Joined: 18 Jul 2009
Posts: 549
edemko
Nice ax-trick, baldr!
One more to a collection.
Never tested.
Code:
format pe gui 4.0
include 'win32ax.inc'

section '' code import readable writable executable
library kernel32,'kernel32.dll',\
        user32,'user32.dll'

include 'api\kernel32.inc'
include 'api\user32.inc'


ARR_START:
arr dd 1,3,2,4,8,5,6,6,9,9,7,8,4,4,4,4,4,0,3,8,0
ARR_END:


entry $
        stdcall bubble32,(ARR_END-ARR_START)/4,arr
        invoke  ExitProcess,0



proc bubble32; sz:dword, src:dword
        xchg    ebx,[esp+4]
        xchg    edx,[esp+8]
        pushfd
        cld
        push    eax ecx esi edi

.loop:  sub     ebx,1
        jbe     .exit
        mov     ecx,ebx
        mov     esi,edx
        mov     edi,edx
  .subloop:
        lodsd
        cmp     eax,[esi]
        jna     .continue
        xchg    eax,[esi]
  .continue:
        stosd
        loop    .subloop
        jmp     .loop

.exit:  pop     edi esi ecx eax
        popfd
        mov     edx,[esp+8]
        mov     ebx,[esp+4]
        ret     8
endp 
    


edit: error fixed
Post 10 May 2010, 16:04
View user's profile Send private message Reply with quote
edemko



Joined: 18 Jul 2009
Posts: 549
edemko
Code:
  .continue: 
        stosd
    

instead of
Code:
        stosd
  .continue: 
    

excuse me if it disturbed understanding
debugged
Post 11 May 2010, 05:31
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on YouTube, Twitter.

Website powered by rwasa.