linux - 如何在 ubuntu 下使用 nasm(程序集)从键盘读取单个字符输入?

标签 linux assembly character nasm tty

我在 ubuntu 下使用 nasm。顺便说一下,我需要从用户键盘获取单个输入字符(比如当程序要求您输入 y/n 时?),因此当按下按键而不按回车键时,我需要读取输入的字符。我用谷歌搜索了很多,但我发现的所有内容都以某种方式与这条线 (int 21h) 相关,这导致了“Segmentation Fault”。请帮我弄清楚如何获取单个字符或如何克服这个段错误。

最佳答案

可以通过汇编完成,但这并不容易。不能使用 int 21h,这是一个 DOS 系统调用,在 Linux 下不可用。

要在类 UNIX 操作系统(例如 Linux)下从终端获取字符,您可以从 STDIN(文件编号 0)读取。通常,read 系统调用将阻塞,直到用户按下回车键。这称为规范模式。要在不等待用户按下 enter 的情况下读取单个字符,您必须首先禁用规范模式。当然,如果您稍后想在程序退出之前进行线路输入,则必须重新启用它。

要在 Linux 上禁用规范模式,您可以使用 ioctl 系统调用向 STDIN 发送一个 IOCTL (IO ControL)。我假设您知道如何从汇编程序进行 Linux 系统调用。

ioctl 系统调用具有三个参数。第一个是将命令发送到的文件 (STDIN),第二个是 IOCTL 编号,第三个通常是指向数据结构的指针。 ioctl 成功时返回 0,失败时返回负错误代码。

您需要的第一个 IOCTL 是 TCGETS(编号 0x5401),它在 termios 结构中获取当前终端参数。第三个参数是指向 termios 结构的指针。从内核源码来看,termios结构定义为:

struct termios {
    tcflag_t c_iflag;               /* input mode flags */
    tcflag_t c_oflag;               /* output mode flags */
    tcflag_t c_cflag;               /* control mode flags */
    tcflag_t c_lflag;               /* local mode flags */
    cc_t c_line;                    /* line discipline */
    cc_t c_cc[NCCS];                /* control characters */
};

其中 tcflag_t 是 32 位长,cc_t 是一个字节长,NCCS 目前定义为 19。请参阅 NASM 手册,了解如何方便地为这样的结构定义和保留空间。

因此,一旦获得当前的 termios,就需要清除规范标志。该标志位于 c_lflag 字段中,掩码为 ICANON (0x00000002)。要清除它,请计算 c_lflag AND(不是 ICANON)。并将结果存储回 c_lflag 字段。

现在您需要通知内核您对 termios 结构的更改。使用 TCSETS(编号 0x5402)ioctl,第三个参数设置您的 termios 结构的地址。

如果一切顺利,终端现在处于非规范模式。您可以通过设置规范标志(通过将 c_lflag 与 ICANON 进行 OR 运算)并再次调用 TCSETS ioctl 来恢复规范模式。 总是在退出前恢复规范模式

正如我所说,这并不容易。

关于linux - 如何在 ubuntu 下使用 nasm(程序集)从键盘读取单个字符输入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3305005/

相关文章:

linux - 输入 "ä"并在 Eclipse 中接收 "ae"

c - Linux 克隆调用的最小堆栈大小?

assembly - 是否可以直接从格式良好的 AST 生成汇编代码而不转换为 IR?

c - 为什么这个 if 部分被编译成无限循环?

python - 使用 Python 查找文件中的字符数

c# - Monodevelop 中的 Visual Studio C# 项目 - GenerateSatelliteAssemblies 和 GenerateTargetFrameworkMonikerAttribute 的错误

linux - 如何在 Linux 上禁用二进制文件的地址空间随机化?

assembly - MMX 和 XMM 寄存器之间的区别?

java - 我如何反转这个基本加密?

c - 从二维数组打印字符时出现颠倒的问号