Чтение ввода с клавиатуры с помощью системных вызовов x64 linux (сборка)

#linux #assembly #system-calls

#linux #сборка #системные вызовы

Вопрос:

Я пытаюсь научиться использовать 64-битный системный вызов Linux в сборке.

Я писал некоторый код для чтения клавиатуры и просто выводил его на экран нажатыми клавишами: я использую sys_read.

Код:

 section .text

global _start

_start:
;write startmsg
mov rax, 1
mov rdi, 1
mov rsi, startmsg
mov rdx, sizestart
syscall
;using sys_read
mov ax, 0
mov rdi, 0
mov rsi, key
mov rdx, 2
syscall
;trying to see if esc is pressed then exit
mov rbx, 0x1b
cmp rbx, key
je _exit

_exit:  
mov rax, 60
mov rdi, 0
syscall

section .bss
key resw 1

section .data
startmsg db 'Press a key', 10
sizestart equ $-startmsg
 

Теперь происходят две вещи:
1) он автоматически печатает на экране клавиши (D 🙂
2) он не завершается, когда я нажимаю esc

Ответ №1:

он автоматически печатает на экране клавиши

Это настройка по умолчанию в Linux (независимо от языка программирования):

  • Ввод с клавиатуры выводится на экран
  • sys_read будет ждать, пока не будет нажата клавиша return (enter)

Чтобы изменить это поведение, должна быть вызвана функция tcsetattr() (на C). Вы должны вызвать функцию tcgetattr() перед тем, как сохранить текущие настройки и восстановить их перед выходом из программы.

Если вы хотите использовать системные вызовы напрямую: tcsetattr и tcgetattr оба используют некоторый sys_ioctl. Чтобы узнать, какой код ioctl () используется, вы можете написать программу на C, выполняющую tcsetattr и tcgetattr, и использовать «strace», чтобы узнать, какие системные вызовы вызываются.

он не завершается, когда я нажимаю esc

В файле есть три проблемы:

  1. Насколько я правильно понимаю, вы читаете два байта — что означает два нажатия клавиш — всякий раз, когда вы вызываете sys_read
  2. sys_read будет ждать, пока не будет нажата клавиша возврата (см. Выше)
  3. Вы сравниваете 64-разрядное значение с фрагментом памяти длиной всего в один (или два) байта (ов).

Вы должны прочитать только один байт с помощью sys_read . Затем вы должны выполнить побочное сравнение вместо 64-разрядного сравнения:

 cmp bl,key
 

вместо:

 cmp rbx,key