Reputation: 13
I need to get user input skipping every second consonant in it. So every second consonant should not be printed out (not just deleted in some process after hitting Enter).
I've got a task from my teacher in assembler language. Currently I'm using NASM on Linux and would like to stick to it.
The problem is that I need to 'overload' user input interrupt and in it I should be able to process that input (skip every second consonant). I've searched the Net and didn't find any suiting answers. Not how to 'catch' user input before buffering and printing it out, nor the way to read a single character without printing it in terminal.
I would like to see an example of replacing (or modifying) the standard input interrupt system call. That would be the ideal case.
The second option is to make your own type of 'handler' getting each char one by one without echoing it and than handling things like Backspace and Enter myself. Just like getch()
in Windows C does. (or 0x16 BIOS interrupt).
Upvotes: 1
Views: 358
Reputation: 1243
Here is an example of what I use to retrieve a single keystroke. Keep in mind, functions keys, arrows and others like HOME, PGDN etc return more than one byte and for that reason I read up to 8 bytes so what's left in the input buffer won't become an artifact of the next write. This snippet was designed as a response system to things like;
Continue [Y/N]
Calling process would read character returned in AL. If it's 0x1b (27 dec / ESC) then we know it's one of the extended keys. As an example, F1 would return 0x504f1b in 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
Upvotes: 1