flat assembler
Message board for the users of flat assembler.

Index > Windows > Simple addition program

Author
Thread Post new topic Reply to topic
Isamaul



Joined: 27 Jan 2014
Posts: 2
Isamaul 27 Jan 2014, 15:57
Hello i have problems with my addition program in fasm.
First of all, my scanf is not reading floats if i change "%d" to "%f".

I have code of adding two numbers. I need to read only numbers with sign, and stop addition while input =0 then display result.


Code:
format PE console
entry start

include 'win32a.inc'

proc Addition stdcall uses ecx edx, a:DWORD
     mov ecx, [a]
     mov edx, [sum]
     add ecx, edx
     mov [sum],ecx


     ret
endp

section '.data' data readable writeable

        RequestInput   db      "Wpisz liczby: ", 0
        Result         db      "Sum: %d", 0
        Input1         dd      "%d", 0
        Input2         dd      "%d", 0
        sum            dd      "%d", 0

        Number1        dd      ?
        Number2        dd      ?

section '.text' code readable executable

        start:
                mov [sum],0
                push RequestInput
                call [printf]

                push Number1
                push Input1
                call [scanf]

                push [Number1]
                call Addition

                push 3
                call Addition
                push 9
                call Addition


        results:

                push [sum]
                push Result
                call [printf]

                call [getchar]

               ; push 0
                call [ExitProcess]

section '.idata' import data readable

        library msvcrt, 'MSVCRT.DLL', \
                kernel, 'KERNEL32.DLL'

        import msvcrt, \
                       printf, 'printf', \
                       scanf, 'scanf', \
                       getchar, 'getchar'

        import kernel, \
                       ExitProcess, 'ExitProcess'   
 
    


So please tell me if i am not wrong.
I need to: save current sum in some registry.
Read input in infinite loop.
Read input, check if 0, if it is, go to displaying results.
If not 0, get value from registry push it into stack, push current input, call Addition.
Post 27 Jan 2014, 15:57
View user's profile Send private message Reply with quote
typedef



Joined: 25 Jul 2010
Posts: 2909
Location: 0x77760000
typedef 27 Jan 2014, 16:55
1st. don't use scanf.
2nd. Use cinvoke or if you have to use call with a C function, restore the stack.
3rd. Use ConsoleAlloc, GetConsoleHandle, ReadFile/WriteFile,
4th. Use atoi (or make your onwn)
Post 27 Jan 2014, 16:55
View user's profile Send private message Reply with quote
Isamaul



Joined: 27 Jan 2014
Posts: 2
Isamaul 27 Jan 2014, 17:20
I modified source to get loop.
No errors now

Code:
format PE console
entry start

include 'win32a.inc'

proc Addition stdcall uses ecx edx, a:DWORD
     mov ecx, [a]
     mov edx, [sum]
     add ecx, edx
     mov [sum],ecx


     ret
endp

section '.data' data readable writeable

        RequestInput   db      "Write number: ", 0
        Result         db      "Sum: %d", 0
        input          dd      "%s", 0
        sum            dd      "%d", 0

        number        dd      ?

section '.text' code readable executable

        start:
                mov [sum],0 ;;set sum to 0 at start
        inputCall:
                      push RequestInput
                      call [printf]

                      push number     ;; push variable
                      push input      ;; get input
                      call [scanf]     ;; do scanf
                      ;; atoi
                      cinvoke atoi, number
                      mov [number],eax
        checkIfZero:
                      mov ecx, [number]    ;; get inserted number
                      cmp ecx,0             ;; check if 0
                      je  results  ;go to results if 0

                      push [number]  ;; not 0, we can sum, push number into stack
                      call Addition   ;; get addition
                      jmp inputCall   ;; loop


        results:

                push [sum]
                push Result
                call [printf]

                call [getchar]

                push 0

                call [ExitProcess]

section '.idata' import data readable

        library msvcrt, 'MSVCRT.DLL', \
                kernel, 'KERNEL32.DLL'

        import msvcrt, \
                       printf, 'printf', \
                       scanf, 'scanf', \
                       getchar, 'getchar',\
                       atoi, 'atoi'

        import kernel, \
                       ExitProcess, 'ExitProcess'   

    


I am new into this, so i do not know what typedef, are you talking about.
1. What should i use instead of scanf, and where can i learn more about that?
2. Why should I?
3. For what should i use that?
Post 27 Jan 2014, 17:20
View user's profile Send private message Reply with quote
typedef



Joined: 25 Jul 2010
Posts: 2909
Location: 0x77760000
typedef 27 Jan 2014, 19:44
Sorry for misleading you with the ConsoleAlloc API. When you specify the EXE type in the PE header as console, the system will spawn the console for you. I thought this was marked as GUI.

Another thing, don't use atoi as it doesn't report errors. Instead strtol will return if there was an error or not.

Anyway,

Quote:

1. What should i use instead of scanf, and where can i learn more about that?
2. Why should I?
3. For what should i use that?


1. Instead of using scanf, read a fixed amount of bytes from the console. Say 12 (12 bytes = 12 possible digits (LONG)).
Then, with that fixed buffer, use something like strtol to do the conversion.

2. I suggest reading calling conventions and the stack : http://en.wikipedia.org/wiki/X86_calling_conventions

3. Using scanf will always expect the input to be what the format specifier indicates. So if you use %d (signed int), and type a string (ie qwerty instead of 1234) in the console, you will get garbage and your app will likely crash.

Code:
format PE console
entry start 

include 'win32a.inc'

FIRST_PARAMETER  EQU DWORD[EBP+0x08]
SECOND_PARAMETER EQU DWORD[EBP+0x0C]

section '.data' data readable writeable

        RequestInput   db      "Enter number [0 to quit] > ", 0
        fmt            db      "Sum : %d", 10,13,0
        buffer         db      16    dup(0)
        bytes_read     dd      0

section '.text' code readable executable 

;
; __stdcall signed int Addition (signed int a, signed int b)
;
Addition:
     push       ebp
     mov        ebp,    esp     ; setting up our stack frame.

     mov        ecx,    FIRST_PARAMETER    ; get a
     mov        eax,    SECOND_PARAMETER   ; get b
     add        eax,    ecx     ; adds ECX to EAX and result is stored in EAX

     pop        ebp             ; restore old stack frame pointer
     ret        4 * 2           ; POP 2 DWORD values from stack

start:
     push       -10                ; Get standard input handle
     call       [GetStdHandle]
     mov         ebx,    eax
     xor         esi,    esi
.input:
     push       RequestInput
     call       [printf]
     add        esp,    4       ; restore the stack

     ; read 12 bytes from console
     push      NULL
     push      bytes_read
     push      12             ; bytes to read
     push      buffer
     push      ebx            ; console handle
     call      [ReadFile]

     ; now attempt to convert the buffer to number
     push      10            ; Our RADIX
     push      NULL          ; NULL
     push      buffer
     call      [strtol]
     add       esp,   4

     ; 0 could be an error or completion signal
     test      eax,   eax
     je       .show_results

.add_number:
     ; add number
     push      esi
     push      eax
     call      Addition
     mov       esi,  eax  ; sum += Addition (input, sum);

     jmp       .input

.show_results:
     push      esi
     push      fmt
     call      [printf]
     add       esp, 4*2

     ; pause the console
     call     [getchar]

     push     0x0
     call     [ExitProcess]

section '.idata' import data readable 

        library msvcrt, 'MSVCRT.DLL', \ 
                kernel, 'KERNEL32.DLL' 

        import msvcrt, \ 
                       printf, 'printf', \ 
                       getchar, 'getchar', \
                       strtol,'strtol'

        import kernel, \ 
                       ExitProcess, 'ExitProcess',\
                       GetStdHandle,'GetStdHandle',\
                       ReadFile,'ReadFile'
    
Post 27 Jan 2014, 19:44
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-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.