汇编:在Windows nasm中处理用户输入

问题描述:

我是asm的新手,正在尝试创建一个简单的hello世界,等待用户按下键结束.目前,hello world一切都很好,但是我从中获得的.exe控制台程序只是立即关闭,而我希望它一直显示在屏幕上,直到用户按下某个键为止. 现在我遇到的问题是,由于某种原因,该程序一直循环运行,搜索用户输入,但是当我强制关闭程序(^ C)时,我可以看到我按下的所有键都写在下一个控制台行上,例如它使用了错误的缓冲区(?)

I'm a newbie to asm and trying to make a simple hello world which awaits for the user to press a key to end. For now the hello world is all good, but the .exe console program i got from this just close instantly while i want it to stay on screen untill the user press a key. Now the problem i have is that for some reason, the program keep looping, searching for user input, but when i force close the program (^C) i can see all the keys i pressed are written on the next console line, like if it was using the wrong buffer (?)

几天来我一直在互联网上搜索修复程序,最后我寻求帮助,因为这使我发疯了^^ 我发现的所有内容主要基于int系统或linux下,而我必须处理Windows api ...

I've been searching a fix all over the internet for a few days and finally I'm asking for help cuz this is driving me crazy ^^ Everything i found is mostly based on int system or under linux, while i have to deal with the windows api...

非常感谢,欢迎您提供任何帮助或提示!

Thank you very much, any help or hint is welcome!

代码:

STD_OUTPUT_HANDLE   equ -11
STD_INPUT_HANDLE    equ -10 
NULL                equ 0

global start
extern ExitProcess, GetStdHandle, WriteConsoleA, ReadConsoleInputA

section .data
msg                 db "Hello World!", 13, 10, 0
msg.len             equ $ - msg
consoleInHandle     dd 1

section .bss
buffer              resd 2
buffer2             resd 2

section .text
    start:

        push    STD_OUTPUT_HANDLE
        call    GetStdHandle

        push    NULL
        push    buffer
        push    msg.len
        push    msg
        push    eax
        call    WriteConsoleA 

    read:

        push STD_INPUT_HANDLE
        call GetStdHandle
        mov [consoleInHandle],eax
        push consoleInHandle
        push dword[buffer2]
        push 1
        push NULL
        call ReadConsoleInputA

        cmp eax,1
        jge exit
        jmp read

    exit:

        push    NULL
        call    ExitProcess

有关Windows功能的详细信息可以在这里找到:

Moar info about windows functions can be found here:

  • ReadConsoleInput
  • WriteConsole

push consoleInHandle推送地址,而不是句柄.您需要push dword [consoleInHandle].相反,对于缓冲区,您要传递地址,因此在那里需要push buffer2.另外,此缓冲区的大小应为INPUT_RECORD结构的大小,我认为该大小为32个字节.

push consoleInHandle pushes the address, not the handle. You want push dword [consoleInHandle]. Conversely, for the buffer you want to pass the address, so you need push buffer2 there. Also, this buffer should be the size of an INPUT_RECORD structure, which I believe is 32 bytes.

更新:正如弗兰克所说,论证顺序也是错误的. 这段代码对我有用(请注意,由于我的环境设置方式,我必须添加@xx stdcall装饰-显然您不需要那些装饰):

Update: As Frank commented, the argument order was also wrong. This code works for me (note I had to add the @xx stdcall decorations due to how my environment is set up - apparently you don't need those):

STD_OUTPUT_HANDLE   equ -11
STD_INPUT_HANDLE    equ -10
NULL                equ 0

global start
extern ExitProcess@4, GetStdHandle@4, WriteConsoleA@20, ReadConsoleInputA@16

section .data
msg                 db "Hello World!", 13, 10, 0
msg.len             equ $ - msg
consoleInHandle     dd 1

section .bss
buffer              resd 2
buffer2             resb 32

section .text
    start:

        push    STD_OUTPUT_HANDLE
        call    GetStdHandle@4

        push    NULL
        push    buffer
        push    msg.len
        push    msg
        push    eax
        call    WriteConsoleA@20

    read:

        push STD_INPUT_HANDLE
        call GetStdHandle@4
        mov [consoleInHandle],eax
        push NULL
        push 1
        push buffer2
        push dword [consoleInHandle]
        call ReadConsoleInputA@16

    exit:

        push    NULL
        call    ExitProcess@4