Как я читаю, отдельный символ ввел с клавиатуры с помощью nasm (блок) под человечностью?

Я использую nasm под человечностью. По тому, как я должен получить единственный вводимый символ от клавиатуры пользователя (как то, когда программа просит у Вас y/n?) поэтому как нажатая клавиша и не нажимая Enter я должен считать вводимый символ. Я погуглил его много, но все, что я нашел, были так или иначе связаны с этой строкой (int 21h) которые приводят к "Отказу Сегментации". Помогите мне понять это, как получить отдельный символ или как к по прибывшему этот отказ сегментации.

6
задан Majid 15 May 2015 в 15:16
поделиться

2 ответа

Это можно сделать из сборки, но это непросто. Вы не можете использовать int 21h, это системный вызов DOS, и он недоступен в Linux.

Чтобы получить символы с терминала в UNIX-подобных операционных системах (например, Linux), вы читаете из STDIN (номер файла 0).Обычно системный вызов чтения блокируется до тех пор, пока пользователь не нажмет клавишу ввода. Это называется каноническим режимом. Чтобы прочитать один символ, не дожидаясь, пока пользователь нажмет клавишу ввода, необходимо сначала отключить канонический режим. Конечно, вам придется снова включить его, если вы хотите вводить строку позже, но до выхода из программы.

Чтобы отключить канонический режим в Linux, вы отправляете IOCTL (IO ControL) на STDIN, используя системный вызов ioctl. Я предполагаю, что вы знаете, как выполнять системные вызовы Linux из ассемблера.

Системный вызов ioctl имеет три параметра. Первый - это файл для отправки команды (STDIN), второй - номер IOCTL,а третий - обычно указатель на структуру данных. ioctl возвращает 0 в случае успеха или отрицательный код ошибки в случае неудачи.

Первый IOCTL, который вам нужен, - это TCGETS (номер 0x5401), который получает текущие параметры терминала в структуре termios. Третий параметр - это указатель на структуру termios. В исходном коде ядра структура termios определяется как:

struct termios {
    tcflag_t c_iflag;               /* input mode flags */
    tcflag_t c_oflag;               /* output mode flags */
    tcflag_t c_cflag;               /* control mode flags */
    tcflag_t c_lflag;               /* local mode flags */
    cc_t c_line;                    /* line discipline */
    cc_t c_cc[NCCS];                /* control characters */
};

где tcflag_t - длина 32 бита, cc_t - длина одного байта, а NCCS в настоящее время определен как 19. См. Руководство по NASM, чтобы узнать, как удобно определить и зарезервировать место для такие структуры.

Итак, как только у вас есть текущие термины, вам нужно очистить канонический флаг. Этот флаг находится в поле c_lflag с маской ICANON (0x00000002). Чтобы очистить его, вычислите c_lflag И (НЕ ICANON). и сохраните результат обратно в поле c_lflag.

Теперь вам нужно уведомить ядро ​​о ваших изменениях в структуре termios. Используйте TCSETS (номер 0x5402) ioctl, с третьим параметром задайте адрес вашей структуры termios.

Если все пойдет хорошо, терминал перешел в неканонический режим. Вы можете восстановить канонический режим, установив канонический флаг (установив OR c_lflag с ICANON) и снова вызвав TCSETS ioctl. всегда восстанавливайте канонический режим перед выходом

Как я уже сказал, это непросто.

11
ответ дан 8 December 2019 в 14:39
поделиться

Простой способ: для программы в текстовом режиме используйте libncurses для доступа к клавиатуре; для графической программы используйте Gtk + .

Сложный путь: предполагая, что программа работает в текстовом режиме, вы должны сказать ядру, что вы хотите вводить один символ, а затем вам придется проделать большую работу по учету и декодированию. Это действительно сложно. Не существует эквивалента старой доброй подпрограммы DOS getch () . Вы можете запустить , чтобы узнать, как это сделать, здесь: Терминал ввода-вывода . Графические программы еще сложнее; API самого низкого уровня для этого - Xlib .

В любом случае, вы сойдете с ума, кодируя все, что есть на ассемблере; вместо этого используйте C.

0
ответ дан 8 December 2019 в 14:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: