如何在ubuntu下使用nasm(程序集)从键盘读取单个字符输入? [英] How do i read single character input from keyboard using nasm (assembly) under ubuntu?

查看:30
本文介绍了如何在ubuntu下使用nasm(程序集)从键盘读取单个字符输入?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 ubuntu 下使用 nasm.顺便说一句,我需要从用户的键盘上获取单个输入字符(比如当程序要求您输入 y/n 时?),以便在按下键而不按 Enter 时,我需要读取输入的字符.我用谷歌搜索了很多,但我发现的所有内容都与导致分段错误"的这一行(int 21h)有关.请帮我弄清楚如何获取单个字符或如何克服这个分段错误.

I'm using nasm under ubuntu. By the way i need to get single input character from user's keyboard (like when a program ask you for y/n ?) so as key pressed and without pressing enter i need to read the entered character. I googled it a lot but all what i found was somehow related to this line (int 21h) which result in "Segmentation Fault". Please help me to figure it out how to get single character or how to over come this segmentation fault.

推荐答案

可以从汇编中完成,但并不容易.你不能使用 int 21h,这是一个 DOS 系统调用,它在 Linux 下不可用.

It can be done from assembly, but it isn't easy. You can't use int 21h, that's a DOS system call and it isn't available under Linux.

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

To get characters from the terminal under UNIX-like operating systems (such as Linux), you read from STDIN (file number 0). Normally, the read system call will block until the user presses enter. This is called canonical mode. To read a single character without waiting for the user to press enter, you must first disable canonical mode. Of course, you'll have to re-enable it if you want line input later on, and before your program exits.

要在 Linux 上禁用规范模式,请使用 ioctl 系统调用向 STDIN 发送 IOCTL(IO 控制).我假设您知道如何从汇编程序中进行 Linux 系统调用.

To disable canonical mode on Linux, you send an IOCTL (IO ControL) to STDIN, using the ioctl syscall. I assume you know how to make Linux system calls from assembler.

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

The ioctl syscall has three parameters. The first is the file to send the command to (STDIN), the second is the IOCTL number, and the third is typically a pointer to a data structure. ioctl returns 0 on success, or a negative error code on fail.

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

The first IOCTL you need is TCGETS (number 0x5401) which gets the current terminal parameters in a termios structure. The third parameter is a pointer to a termios structure. From the kernel source, the termios structure is defined as:

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 为 1 个字节长,NCCS 当前定义为 19.请参阅 NASM 手册了解如何方便地为此类结构定义和保留空间.

where tcflag_t is 32 bits long, cc_t is one byte long, and NCCS is currently defined as 19. See the NASM manual for how you can conveniently define and reserve space for structures like this.

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

So once you've got the current termios, you need to clear the canonical flag. This flag is in the c_lflag field, with mask ICANON (0x00000002). To clear it, compute c_lflag AND (NOT ICANON). and store the result back into the c_lflag field.

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

Now you need to notify the kernel of your changes to the termios structure. Use the TCSETS (number 0x5402) ioctl, with the third parameter set the the address of your termios structure.

如果一切顺利,终端现在处于非规范模式.您可以通过设置规范标志(通过或操作 c_lflag 与 ICANON)并再次调用 TCSETS ioctl 来恢复规范模式.在退出之前总是恢复规范模式

If all goes well, the terminal is now in non-canonical mode. You can restore canonical mode by setting the canonical flag (by ORing c_lflag with ICANON) and calling the TCSETS ioctl again. always restore canonical mode before you exit

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

As I said, it isn't easy.

这篇关于如何在ubuntu下使用nasm(程序集)从键盘读取单个字符输入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆