In x64 NASM, if I wanted to read one character from STDIN into an 8-bit register, the only method I know is this:
xor rax, rax
xor rdi, rdi
mov rsi, buffer
mov rdx, 1
syscall
mov al, byte [buffer]
Would it be possible to read the character directly into the register, without using a buffer? (I am using Ubuntu 18.04)
One thing you want to keep in mind is that a keypress does not necessarily equate to one byte. As an example, function keys can return up to 5 bytes. This method doesn't require a specially allocated buffer, but conceptually, space on stack could be considered a buffer.
See comment below edi, 8 should be edx, 8
mov edi, 8 ; Size of one QWORD
push rax ; Could be any register, we just need 8 bytes
mov rsi, rsp
xor edi, edi ; Essentially STDIN
mov eax, edi ; SYS_READ
syscall
pop rax ; Bytes
If you pressed one of the 96 keys from space (20H) to tilde (7FH) then a your result will be returned in AL. However if AL = 27 (1BH) then the remaining bits (08-3F) will have the other relevant data.
I use this procedure to accept a single keystroke without echo and the need to press return to accept entry.
; ============================================================================= ; 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 STDOUT 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 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