Как «тихо» получить пользовательский ввод с терминала в Linux? - PullRequest
1 голос
/ 09 ноября 2019

Мне нужно, чтобы пользовательский ввод пропускал каждую вторую согласную. Таким образом, каждый второй согласный должен не быть распечатан (не просто удален в некотором процессе после нажатия Enter).

У меня есть задание от моего учителя по ассемблеруязык. В настоящее время я использую NASM в Linux и хотел бы придерживаться его.

Проблема в том, что мне нужно «перегрузить» прерывание пользовательского ввода, и в нем я смогу обработать этот ввод (пропустить каждую вторую согласную). Я искал в сети и не нашел подходящих ответов. Не о том, как «перехватить» пользовательский ввод перед буферизацией и распечаткой, ни о способе чтения одного символа без печати в терминале.

Я хотел бы увидеть пример замены (или изменения) стандартасистемный вызов входного прерывания. Это был бы идеальный случай.

Второй вариант - сделать свой собственный тип «обработчика», получая каждый символ один за другим, не повторяя его, и чем обрабатывать такие вещи, как Backspace и Enter себе. Точно так же, как getch() в Windows C. (или прерывание BIOS 0x16).

1 Ответ

1 голос
/ 09 ноября 2019

Вот пример того, что я использую для получения одного нажатия клавиши. Имейте в виду, функциональные клавиши, стрелки и другие, такие как HOME, PGDN и т. Д., Возвращают более одного байта, и по этой причине я прочитал до 8 байтов, поэтому то, что осталось во входном буфере, не станет артефактом следующей записи. Этот фрагмент был разработан как система реагирования на такие вещи, как;

Продолжить [Д / Н]

В процессе вызова будет считан символ, возвращенный в AL. Если это 0x1b (27 декабря / ESC), то мы знаем, что это один из расширенных ключей. Например, F1 вернет 0x504f1b в EAX.

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
...