LINUX.ORG.RU

NASM. Не могу избежать паузы с sys_read в консольном приложении.

 , , , ,


0

2

Ребята, хелб!

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

Вот сниппет (Нашинковал его, что бы не захламлять тут все):

1 sys_read equ 0
2 sys_write equ 1
3 sys_ioctl equ 16
4 sys_nanosleep equ 35
5 sys_exit equ 60 6
7 tcgets equ 0x5401
8 tcsets equ 0x5402
9 tiocgwinsz equ 0x5413
10
11 stdin equ 0
12 stdout equ 1

… … …

132 read_ioc:
133 mov rax, sys_ioctl
134 mov rdi, stdin
135 mov rsi, tcgets
136 mov rdx, default_par
137 syscall
138
139 mov rax, sys_ioctl
140 mov rdi, stdin
141 mov rsi, tcgets
142 mov rdx, modified_par
143 syscall
144
145 and dword [modified_par + 0], -1516
146 and dword [modified_par + 4], -2
147 and dword [modified_par + 12], -32844
148 and dword [modified_par + 8], -305
149 and dword [modified_par + 8], 48
150
151 mov rax, sys_ioctl
152 mov rdi, stdin
153 mov rsi, tcsets
154 mov rdx, modified_par
155 syscall
156
157 call check_input
158
159 mov rax, sys_ioctl
160 mov rdi, stdin
161 mov rsi, tcsets
162 mov rdx, default_par
163 syscall
164
165 ret

… … …

167 check_input:
168 mov rax, sys_read
169 mov rdi, stdin
170 mov rdx, 8
171 mov rsi, input_buffer
172 syscall
173
174 ret



Последнее исправление: lolybuff (всего исправлений: 2)
Ответ на: комментарий от lolybuff

Ни NASM ни 32/64 тут ни при чём, изучай системные вызовы. Они от языка не зависят. Как сделать произвольный системный вызов из ассемблера я вижу ты уже знаешь.

firkax ★★★★★
()

stdin

так ты будешь читать не нажатые клавиши, а то, что терминал посылает в твою программу. оно, конечно, можно и так, но так получается некоторый суррогат.

посмотри лучше как делано в evtest. тебе нужно взять что-то из select/poll/epoll (man 2 select, например), чтобы проверять, есть ли новая информация в файле, структуру struct input_event из <linux/input.h> и читать напрямую из файла /dev/input/event? а не из stdin. какой именно event тебе нужен можно узнать из cat /proc/bus/input/devices.

пользователь, обычно, не имеет доступа к /dev/input/event*, так что ещё придётся разобраться с правами.

если тебе нужны именно

читать нажатые на текущий момент клавиши

anonymous
()

Тебе два ответа нужно совместить

NASM. Не могу избежать паузы с sys_read в консольном приложении. (комментарий)

переключить stdin в non-blocking mode

чтобы читать ввод не ожидая клавиши Enter

и

NASM. Не могу избежать паузы с sys_read в консольном приложении. (комментарий)

тебе нужно взять что-то из select/poll/epoll

чтобы определить нажата клавиша или нет. Таймаут в ноль и функция сразу завершится, а по коду возврата и errno определишь причину - данные готовы или произошёл таймаут.

alman ★★★
()
Ответ на: комментарий от alman

Я поискал информацию по твоему ответу

Правильно я понимаю, что ты имеешь в виду параметр VTIME и VMIN в структуре termios?

Единственное, не очень понимаю, non-blocking mode при нулевом таймауте нужен?

lolybuff
() автор топика
Ответ на: комментарий от lolybuff

ты имеешь в виду параметр VTIME и VMIN в структуре termios?

Нет. Вероятно это можно использовать, но это костыль. ИМХО.

Вот так выключить ожидание Enter:

struct termios old_tio, new_tio;
/* get the terminal settings for stdin */
tcgetattr(STDIN_FILENO, &old_tio);
/* we want to keep the old setting to restore them a the end */
new_tio = old_tio;
/* disable canonical mode (buffered i/o) and local echo */
new_tio.c_lflag &=(~ICANON );/*& ~ECHOE  );*/
/* set the new settings immediately */
tcsetattr(STDIN_FILENO,TCSANOW,&new_tio);
for(;1;) {    

    c = getchar(); 
    switch(c) {...}
 }

Но блокироваться ввод всё равно будет до нажатия на клавишу. Чтобы исключить блокировку, используй select или poll на STDIN_FILENO.

alman ★★★
()