C++:使用程序集在不按回车键的情况下询问用户输入?[复制]

C++ : Ask user input without pressing enter using assembly? [duplicate]

提问人:Thibault de Villèle 提问时间:4/18/2017 更新时间:4/18/2017 访问量:887

问:

我想创建一个菜单,用户只需按下一个按钮,然后从屏幕上的选项中进行选择。

我试过使用 、 、 甚至 .getchar()fgets(stdin)gets()getch()

我已经转向使用一些内联程序集从 stdin 中获取一个字符。 我使用的代码如下:

char io::u_i() {
    char a;
    __asm__("INT 0x21;"     // Interruption vector for input
            "MOV %1, %0;"   // Move from stdin to a
            : "=r" (a)      // Output variable
            : "r" (stdin)   // Input variable
            : "%1"          // Obfuscated registers
            );
    return a;
}

如果我足够了解 G++ 如何编译汇编,它应该发送一个中断向量(0x21是我在网上找到的那个,要求按键),然后将 G++ 将接受输入的寄存器中的内容(在本例中如此)移动到 G++ 将接受输出的寄存器。stdin

我之前做过一些常规汇编(AT&T 语法),没有征求用户输入。所以这对我来说是一个新领域。G++ 告诉我代码中此时存在错误:

sources/io.cpp:7:11: error: invalid operand for instruction
                __asm__("INT 0x21;"     // Interruption vector for input
                        ^
<inline asm>:1:6: note: instantiated into assembly here
        INT 0x21;MOV %rcx, %r8b;
            ^~~~~
sources/io.cpp:7:11: error: unknown use of instruction mnemonic without a size suffix
                __asm__("INT 0x21;"     // Interruption vector for input
                        ^
<inline asm>:1:11: note: instantiated into assembly here
        INT 0x21;MOV %rcx, %r8b;
                 ^

但是在我对汇编的介绍中,除了 之外不需要其他任何东西,所以我在这里看不到 G++ 对我的期望。是否有针对内联 ASM 和 AT&T 语法的特定编译器选项?INT 0x21;

我的一段代码甚至会做我所期望的吗?

PS :如果它可以以任何方式帮助您,我正在macOS Sierra上编译它,这是以下输出:g++ --version

Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 8.1.0 (clang-802.0.38)
Target: x86_64-apple-darwin16.5.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
C GCC 程序集 输入 G++

评论

1赞 Michael Petch 4/18/2017
在 AT&T 语法中,像 0x21 这样的即时值需要在它前面加上 a。.但我更担心的是,这不会在 Linux 或 OSX 等操作系统下作为用户应用程序运行(您似乎在 OSX 上)。 通常是 DOS 中断。您打算在什么环境中运行此程序?是操作系统开发吗?$Int $0x21int $0x21
0赞 Ap31 4/18/2017
奇怪,+应该足够了kbhit()getch()
0赞 Michael Petch 4/18/2017
其他问题。使用内联扩展 asm 时,所有寄存器名称都必须具有 a 而不是 .所以应该等等。同样,您可以将 64 位寄存器移动到您尝试使用的 8 位寄存器。%%%%rcx%%rcxMOV %rcx, %r8b
1赞 Ross Ridge 4/18/2017
不能在 Mac OS 上使用 MS-DOS API。若要消除用户在程序看到用户输入之前按 Enter 的需要,您需要使用更改为非规范输入处理。为此,您不需要使用程序集。查看 developer.apple.com/legacy/library/documentation/Darwin/...或者,您可能希望使用诅咒库,该库具有更简单的界面来处理此类事情。tcsetattr
1赞 Michael Petch 4/18/2017
如果您正在寻找 OS/X 和 Linux 解决方案,您可能希望查看以下 SO 答案:stackoverflow.com/a/7469410/3857942 。它使用修改终端 io 设置的功能来创建类似的功能。termiosgetch

答:

1赞 Thibault de Villèle 4/18/2017 #1

好的,找到了一个不需要汇编代码的解决方案。

它基本上是对这个线程的轻微调整,使其在 g++ 编译器下以 C++ 编译。

只需要更改代码中调用的变量的名称,使其在 g++ 下编译即可。感谢您的帮助,我希望这也能回答其他人的问题。new