flat assembler
Message board for the users of flat assembler.
![]() |
Author |
|
Killerkarnickel 10 May 2010, 08:40
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 |
|||
![]() |
|
DOS386 10 May 2010, 09:14
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 ![]() I'm not going to comment on your WriteConsole usage, I didn't test your code and I'm using other style ![]() Last edited by DOS386 on 10 May 2010, 09:16; edited 1 time in total |
|||
![]() |
|
Killerkarnickel 10 May 2010, 09:16
@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. |
|||
![]() |
|
DOS386 10 May 2010, 09:19
Again, size of the elements is crucial. Hint: Start with fixed size of 1 Byte or 4 Byte's
![]() ![]() EDIT: then your element size is 3 Byte's (doable but not good) |
|||
![]() |
|
Killerkarnickel 10 May 2010, 09:37
Ok, now I have "9608524317" in my File. 10 Bytes in a row. But I'am still not able to swap two values...
|
|||
![]() |
|
DOS386 10 May 2010, 09:45
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 |
|||
![]() |
|
Killerkarnickel 10 May 2010, 09:56
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? |
|||
![]() |
|
DOS386 10 May 2010, 10:00
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 ![]() > 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. |
|||
![]() |
|
Killerkarnickel 10 May 2010, 10:38
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. |
|||
![]() |
|
DOS386 10 May 2010, 10:43
> 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]. |
|||
![]() |
|
Killerkarnickel 10 May 2010, 10:51
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 |
|||
![]() |
|
DOS386 10 May 2010, 11:19
> Here is an working MASM Example:
> print str$([esi]),13,10 BAYSIC ??? ![]() > narr dd 1,9,2,8,3,7,4,6,5,0 ; 10 unsorted numbers dd is 4 Byte's ![]() |
|||
![]() |
|
Killerkarnickel 10 May 2010, 11:23
That MASM example is in included in the standard installation. I don't like the MASM ... that's why I use FASM
![]() 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. |
|||
![]() |
|
baldr 10 May 2010, 14:46
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. ![]() 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 |
|||
![]() |
|
edemko 10 May 2010, 16:04
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 |
|||
![]() |
|
edemko 11 May 2010, 05:31
Code:
.continue:
stosd
instead of Code:
stosd
.continue:
excuse me if it disturbed understanding debugged |
|||
![]() |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.