首页 > 解决方案 > 如何“静默”地从 Linux 上的终端获取用户输入?

问题描述

我需要让用户输入跳过其中的每一秒辅音。所以每个第二个辅音应该被打印出来(不仅仅是在按下 Enter 后在某些过程中删除)。

我从我的老师那里得到了一个汇编语言的任务。目前我在 Linux 上使用 NASM 并希望坚持下去。

问题是我需要“重载”用户输入中断,并且在其中我应该能够处理该输入(每隔一个辅音跳过一次)。我已经搜索了网络并没有找到任何合适的答案。不是如何在缓冲和打印出来之前“捕获”用户输入,也不是在终端不打印的情况下读取单个字符的方法。

我想看一个替换(或修改)标准输入中断系统调用的例子。那将是理想的情况。

第二种选择是让您自己的“处理程序”类型一个接一个地获取每个字符而不回显它,而不是处理诸如 Backspace 和 Enter 我自己之类的事情。就像getch()在 Windows C 中一样。(或 0x16 BIOS 中断)。

标签: linuxassemblyinputnasmtty

解决方案


这是我用来检索单个击键的示例。请记住,功能键、箭头和其他,如 HOME、PGDN 等返回超过一个字节,因此我最多读取 8 个字节,因此输入缓冲区中剩余的内容不会成为下一次写入的工件。该片段被设计为对以下内容的响应系统;

继续 [是/否]

调用进程将读取 AL 中返回的字符。如果它是 0x1b (27 dec / ESC),那么我们知道它是扩展键之一。例如,F1 将在 EAX 中返回 0x504f1b。

USE64

      sys_read      equ      0
      sys_write     equ      1
      sys_ioctl     equ     16

      %define      ICANON      2
      %define        ECHO      8
      %define      TCGETS      0x5401
      %define      TCPUTS      0X5402

            section    .text
    ; =============================================================================
    ; Accept a single key press from operator and return the result that may be
    ; up to 5 bytes in length.

    ;    LEAVE: RAX = Byte[s] returned by SYS_READ
    ; -----------------------------------------------------------------------------

      %define   c_lflag     rdx + 12
      %define      keys     rbp +  8
      %define      MASK     ICANON | ECHO

      STK_SIZE  equ 56              ; Room for 36 byte termios structure

      QueryKey:

            xor     eax, eax
            push    rax             ; This is where result will be stored.

            push    rbp
            mov     rbp, rsp
            sub     rsp, STK_SIZE

            push    r11             ; Modified by SYSCALL
            push    rbx
            push    rdx
            push    rcx
            push    rdi
            push    rsi             ; With size of 56, stack is now QWORD aligned

            mov     edi, eax            ; Equivalent to setting EDI to STDIN
            mov     esi, TCGETS
            lea     rdx, [rbp-STK_SIZE] ; Points to TERMIOS buffer on stack
            mov      al, sys_ioctl
            syscall

            lea     rbx, [c_lflag]
            and     byte [rbx], ~(MASK)
            inc     esi                 ; RSI = TCPUTS
            push    rsi
            mov      al, sys_ioctl
            push    rax
            syscall

       ; Wait for keypress from operator.

            lea     rsi, [keys]         ; Set buffer for input
            push    rdx
            mov     edx, 8              ; Read QWORD bytes max
            mov      al, sys_read
            syscall

NOTE: The code you need could go here

            pop     rdx                 ; Points back to TERMIOS
            pop     rax
            pop     rsi                 ; TCPUTS again
            or      byte [rbx], MASK
            syscall

            pop     rsi
            pop     rdi
            pop     rcx
            pop     rdx
            pop     rbx
            pop     r11

            leave
            pop        rax              ; Return up to 8 characters
            ret

推荐阅读