装配计数程序

时间:2013-03-16 15:33:44

标签: windows loops assembly x86 fasm

我是装配新手,我正在尝试制作一个最高可达10,000的程序并退出。我正在使用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                                                                                                          `

它应该打印1号2号码3等,但它打印数字2号码2号码2号码2号码等一段时间然后退出,而不等待用户输入。我的代码出了什么问题?

编辑:我开始工作了!工作代码:

 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

2 个答案:

答案 0 :(得分:3)

库函数根据自己的需要使用寄存器,不会将它们恢复为原始值。如果你不想丢失它,你需要在内存中保持价值。最简单的方法是使用stack:

push eax ; put value of eax on the top of stack

pop eax  ; remove value from top of stack, save it in eax.

答案 1 :(得分:1)

在调用wsprintf之后,您无需查找字符串的长度,因为它返回复制到缓冲区的字符数。

接下来,有一个名为Application binary interface (ABI)的内容涵盖了许多细节,例如Calling Conventions

当您处理Windows API或C运行时时,他们会遵循这些调用约定,其中esiediebxebp和{{ 1}}在函数调用中保存。这意味着,如果你在其中一个寄存器中有一个值,然后调用一个API函数,那么该值在调用后仍然是相同的。

不需要保存

espeaxecx,因此在通话之前您在这些寄存器中拥有的任何内容都不保证是相同的。如果您在这些寄存器中有某些内容,并且在调用后需要该值,则需要使用edx

保存到变量或堆栈中

push用于返回值。

话虽如此,在此示例中,我使用eax作为循环计数器,并使用ebx作为要打印的当前数字,因为这些值将在API调用中保持不变。

这是NASM,但它会给你和想法。

esi