My implementation of single keystroke without echo. In the course of developing these algos, I discovered for as far as I've gotten anyway, READ, WRITE & IOCTL don't differenciate between STDIN and STDOUT.
Previous state is an error. If STDOUT = 1 is not used, redirection does not work
Preamble to application gets current settings
enter 40, 0
mov [Termios], rsp ; Save global copy of termios
; Read terminal parameters for toggle functionality
mov ax, TCGETS
mov rsi, rax
mov rdx, rsp
mov ax, SYS_IOCTL
syscall
push qword [rsp + 12] ; Permanent copy of defaults
Postamble restores default, but if app craters before getting here, this may be a little mute
; Before we quit, make sure console get set back to defaults
pop rax ; Get defaults
cmp [rsp + 12], rax
jz .Done ; Nothing to do, all is ok
; Set console back to its defaults
mov [rsp + 12], rax
xor rax, rax
mov ax, TCSETS
mov rsi, rax
mov rdx, rsp
mov ax, SYS_IOCTL
syscall
This bit toggles mode off and on, so caller can leave in a certain mode for whatever time.
; =============================================================================================
; TOGGLE: Each call to toggle will turn canonical and echo off or on
; ---------------------------------------------------------------------------------------------
Toggle:
; Maybe there could be a better way to nullify RAX, RSI & RDI
xor rax, rax
push rax
pop rdi
push rax
pop rsi
mov si, TCSETS
mov al, SYS_IOCTL
mov rdx, [Termios] ; Get pointer to termios structure
xor word [rdx + 12], ICANON | ECHO
syscall
ret
I will have another version of this for menu selection probably with a switch and an array of pointers corresponding to A-Z let say
; =============================================================================================
; QUERY: Gets a single keystroke from operator that must be 'Y' or 'N', case insensitive
; ENTRY: RSI = Pointer to routines prompt string
; FLAGS: ZF = 1 if "Yes", otherwise zero
; ---------------------------------------------------------------------------------------------
Query:
enter 4, 0
call Console ; Display prompt associated with input
call Toggle ; Switch to non-canonical, no echo
; Setup for getting single key input
xor rdx, rdx
mov dl, 1
mov rsi, rsp
; Keep doing this until operator enters Y or N
.Again call Keyboard ; Get response from operator
mov al, [rsi]
and al, 0x5f ; Get character and convert to uppercase
cmp al, 'Y'
jz .Done
cmp al, 'N'
jnz .Again
inc al ; Bump so ZF = 0
; We've gotten a Y or N response and ZR has been set
.Done pushf
call Toggle
popf
leave
ret
Needed to add preserving flags @ .Done