Search code examples
windowsloopsassemblyx86fasm

assembly counting program


I am new to assembly and I am trying to make a program that counts up to 10,000 and exits. I am using fasm `

    include 'include/win32ax.inc'

   .data

   inchar     DB ?
   numwritten DD ?
   numread    DD ?
   outhandle  DD ?
   inhandle   DD ?
    strFormat  DB "Number %d ",0
   strBuff    RB 64

   .code
     start:


   ;set up console
    invoke  AllocConsole
    invoke  GetStdHandle,STD_OUTPUT_HANDLE
    mov [outhandle],eax
    invoke  GetStdHandle,STD_INPUT_HANDLE
    mov [inhandle],eax

    ;loop starts here
    mov eax, 0
    LoopStart:
    add eax,1



    invoke wsprintf, strBuff, strFormat, eax   ;convert number to String.

    ;the number eax is now in string form in strBuff

            ;find out the string length of strBuff
    mov ecx,-1
    mov al,0
    mov edi,strBuff
    cld
    repne scasb
    not ecx
    dec ecx
         ;ecx is now the length.



    invoke  WriteConsole,[outhandle],strBuff,ecx,numwritten,0   ;write to console
    ;loop
    cmp eax, 10000;loop compare
    jne LoopStart;jump to start of loop

    invoke  ReadConsole,[inhandle],inchar,1,numread,0 ;give the user a chance to read console output before exit
    invoke  ExitProcess,0


     .end start                                                                                                          `

It is supposed to print Number 1 Number 2 Number 3 etc. but instead it prints Number 2 Number 2 Number 2 Number 2 Number 2 etc. for a while then exits, without waiting for the users input. what is wrong with my code?

Edit: I got it to work! The working code:

 include 'include/win32ax.inc'

    .data

       inchar     DB ?
       numwritten DD ?
        numread    DD ?
      outhandle  DD ?
        inhandle   DD ?
         strFormat  DB "Number %d ",0
          strBuff    RB 64
         number DD ?

          .code
        start:


          ;set up console
         invoke  AllocConsole
          invoke  GetStdHandle,STD_OUTPUT_HANDLE
             mov [outhandle],eax
           invoke  GetStdHandle,STD_INPUT_HANDLE
            mov [inhandle],eax

         ;loop starts here
           mov eax, 0
         LoopStart:
              add eax,1
            mov [number],eax
             mov edi, eax
             push eax
             invoke wsprintf, strBuff, strFormat, edi  ;convert number to String.
            add     esp, 4 * 3


           pop eax
           ;the number eax is now in string form in strBuff

             ;find out the string length of strBuff
             mov ecx,-1
             mov al,0
              mov edi,strBuff
               cld
              repne scasb
             not ecx
              dec ecx
                ;ecx is now the length.


              push eax
       invoke  WriteConsole,[outhandle],strBuff,ecx,numwritten,0   ;write to console
    pop eax
    ;loop
    mov eax, [number]
    cmp eax, 10000;loop compare
    jne LoopStart;jump to start of loop

    invoke  ReadConsole,[inhandle],inchar,1,numread,0 ;give the user a chance to read console output before exit
    invoke  ExitProcess,0

.end start


Solution

  • Library functions use registers for their own needs and do not restore them to original value. You need to keep value in memory if you don't want to lose it. The simplest way is to use stack:

    push eax ; put value of eax on the top of stack
    
    pop eax  ; remove value from top of stack, save it in eax.