|
%define STDIN_FILENO 0 |
|
%define TCSAFLUSH 2 |
|
%define VMIN 6 |
|
%define VTIME 5 |
|
%define BRKINT 0x2 |
|
%define ICRNL 0x100 |
|
%define INPCK 0x10 |
|
%define ISTRIP 0x20 |
|
%define IXON 0x400 |
|
%define OPOST 0x1 |
|
%define CS8 0x30 |
|
%define ECHO 0x8 |
|
%define ICANON 0x2 |
|
%define IEXTEN 0x8000 |
|
%define ISIG 0x1 |
|
|
|
%macro get_termios 1 |
|
mov rdi, STDIN_FILENO |
|
mov rsi, %1 |
|
call tcgetattr |
|
mov rdi, err_tcgetattr |
|
cmp rax, -1 |
|
je die |
|
%endmacro |
|
|
|
%macro set_termios 1 |
|
mov rdi, STDIN_FILENO |
|
mov rsi, TCSAFLUSH |
|
mov rdx, %1 |
|
call tcsetattr |
|
mov rdi, err_tcsetattr |
|
cmp rax, -1 |
|
je die |
|
%endmacro |
|
|
|
%macro print 1 |
|
mov rdi, %1 |
|
xor rax, rax |
|
call printf |
|
%endmacro |
|
|
|
global main |
|
extern printf, perror, tcsetattr, tcgetattr, read, iscntrl |
|
|
|
section .data |
|
|
|
err_read: |
|
db "read", 0 |
|
err_tcsetattr: |
|
db "tcsetattr", 0 |
|
err_tcgetattr: |
|
db "tcgetattr", 0 |
|
output1: |
|
db "%d", 0xd, 0xa, 0 |
|
output2: |
|
db "%d ('%c')", 0xd, 0xa, 0 |
|
ctrl_check: |
|
dd 0x1f |
|
intro: |
|
db "Type from your keyboard. Press CTRL + q to exit.", 0xd, 0xa, 0 |
|
|
|
struc TERMIOS |
|
c_iflag: resd 1 |
|
c_oflag: resd 1 |
|
c_cflag: resd 1 |
|
c_lflag: resd 1 |
|
c_cc: resb 255 |
|
endstruc |
|
|
|
orig_termios: istruc TERMIOS |
|
at c_iflag, dd 0 |
|
at c_oflag, dd 0 |
|
at c_cflag, dd 0 |
|
at c_lflag, dd 0 |
|
at c_cc, db "" |
|
iend |
|
|
|
raw_termios: istruc TERMIOS |
|
at c_iflag, dd 0 |
|
at c_oflag, dd 0 |
|
at c_cflag, dd 0 |
|
at c_lflag, dd 0 |
|
at c_cc, db "" |
|
iend |
|
|
|
char_quit: |
|
dd 'q' |
|
|
|
section .bss |
|
input_char: |
|
resb 1 |
|
|
|
section .txt |
|
|
|
main: |
|
print intro |
|
get_termios orig_termios |
|
get_termios raw_termios |
|
|
|
;enable raw mode |
|
;set c_iflag |
|
mov r15, BRKINT |
|
or r15, ICRNL |
|
or r15, INPCK |
|
or r15, ISTRIP |
|
or r15, IXON |
|
not r15 |
|
mov r14, [raw_termios + c_iflag] |
|
and r14, r15 |
|
mov [raw_termios + c_iflag], r14 |
|
|
|
;set c_oflag |
|
mov r15, OPOST |
|
not r15 |
|
mov r14, [raw_termios + c_oflag] |
|
and r14, r15 |
|
mov [raw_termios + c_oflag], r14 |
|
|
|
;set c_cflag |
|
mov r15, CS8 |
|
mov r14, [raw_termios + c_cflag] |
|
or r14, r15 |
|
mov [raw_termios + c_cflag], r14 |
|
|
|
;set c_lflag |
|
mov r15, ECHO |
|
or r15, ICANON |
|
or r15, IEXTEN |
|
or r15, ISIG |
|
not r15 |
|
mov r14, [raw_termios + c_lflag] |
|
and r14, r15 |
|
mov [raw_termios + c_lflag], r14 |
|
|
|
;set VMIN and VTIME |
|
mov r15, raw_termios + c_cc |
|
mov byte [r15 + VMIN], 0 |
|
mov byte [r15 + VTIME], 1 |
|
mov [raw_termios + c_cc], r15 |
|
|
|
set_termios raw_termios |
|
;end of enable raw mode |
|
|
|
main_loop: |
|
mov [input_char], byte 0 |
|
mov rdi, STDIN_FILENO |
|
mov rsi, input_char |
|
mov rdx, 1 |
|
call read |
|
mov rdi, err_read |
|
cmp rax, -1 |
|
je die |
|
|
|
|
|
mov rdi, [input_char] |
|
call iscntrl |
|
cmp rax, 0 |
|
je isnotctrl |
|
|
|
cmp byte [input_char], 0 |
|
je ender |
|
|
|
mov rsi, [input_char] |
|
print output1 |
|
|
|
ender: |
|
mov r11, [ctrl_check] |
|
and r11, [char_quit] |
|
cmp r11, [input_char] |
|
je break |
|
|
|
jmp main_loop |
|
|
|
isnotctrl: |
|
mov rdx, [input_char] |
|
mov rsi, [input_char] |
|
print output2 |
|
|
|
jmp ender |
|
|
|
break: |
|
set_termios orig_termios |
|
mov rdi, 0 |
|
jmp exit |
|
|
|
die: |
|
call perror |
|
mov rdi, 1 |
|
call exit |
|
|
|
exit: |
|
mov rax, 0x3c |
|
syscall |
|
ret |