【问题标题】:Assembly : Dealing with user input in windows nasm程序集:在 windows nasm 中处理用户输入
【发布时间】:2012-11-14 08:09:02
【问题描述】:

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

我已经在互联网上搜索了几天的修复程序,最后我正在寻求帮助,因为这让我发疯了 ^^ 我发现的一切大多是基于int系统或linux下的,而我必须处理windows api......

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

代码:

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 信息可以在这里找到:

【问题讨论】:

  • 我很确定你想要push dword [consoleInHandle](或者只是push eax)——你正在推送变量的地址。我很确定你想要push buffer2 - 地址,而不是[contents]。我怀疑你以错误的顺序推动它们 - 手柄应该在最后(不太确定)......
  • thx @Frank,我修改了那个,但恐怕这并不能解决问题:/我仍然无法检测到任何用户输入,当我强制我的程序停止时我可以看看我在下一个命令行上输入的字符......而且,我很确定参数的顺序,因为我检查了很多次。快速浏览一下我在第一篇文章中提供的 microsoft doc 链接 :)

标签: windows assembly io nasm


【解决方案1】:

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

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

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

【讨论】:

  • 谢谢,现在我知道我是否对 [] 表示法感到困惑 -_- 至于 de INPUT_RECORD 的事情,我必须做这样的事情吗?:asmcommunity.net/board/index.php?topic=5983.0
  • nb 我试过 buffer2 resb 32 但这并没有解决问题
  • 谢谢 :) 这听起来像是一个愚蠢的问题,但我必须链接什么库才能让它工作?它正在使用 nasm 进行编译,但我的链接器出现错误。我使用 GoLink:GoLink.exe /console /entry start simple_hw2.obj kernel32.dll 并收到此错误消息:“目标文件中未定义以下符号:- ExitProcess@4 GetStdHandle@4 WriteConsoleA@20 ReadConsoleInputA @16 输出文件未生成”
  • 正如我在答案中所写,您不需要 @xx 后缀。我使用需要它的 gnu mingw 工具。只需删除它们。
  • aaw 这解释了一切:$ 并且它有效,哇!非常感谢,我对这个很困惑>
猜你喜欢
  • 1970-01-01
  • 2012-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-19
相关资源
最近更新 更多