Сборка считывает байт из STDIN непосредственно в регистр - PullRequest
1 голос
/ 04 марта 2020

В x64 NASM, если бы я хотел прочитать один символ из STDIN в 8-битный регистр, единственный известный мне метод это:

xor rax, rax
xor rdi, rdi
mov rsi, buffer
mov rdx, 1
syscall
mov al, byte [buffer]

Было бы возможно прочитать символ непосредственно в регистр, без использования буфера? (Я использую Ubuntu 18.04)

1 Ответ

1 голос
/ 04 марта 2020

Одна вещь, которую вы хотите иметь в виду, заключается в том, что нажатие клавиши не обязательно равняется одному байту. Например, функциональные клавиши могут возвращать до 5 байтов. Этот метод не требует специально выделенного буфера, но концептуально пространство в стеке можно считать буфером.

См. Комментарий ниже edi, 8 должно быть edx , 8

    mov     edi, 8                ; Size of one QWORD
    push    rax                   ; Could be any register, we just need 8 bytes
    mov     rsi, rsp
    xor     edi, edi              ; Essentially STDIN
    mov     eax, edi              ; SYS_READ
    syscall
    pop     rax                   ; Bytes

Если вы нажали одну из 96 клавиш из пробела (20H) для тильды (7FH), тогда ваш результат будет возвращен в AL. Однако, если AL = 27 (1BH), то остальные биты (08-3F) будут иметь другие соответствующие данные.

Я использую эту процедуру, чтобы принять одно нажатие клавиши без эха и необходимость нажать клавишу возврата, чтобы принять ввод .

; =============================================================================
; 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 STDOUT
        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

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