问题
I'm trying to learn how to use linux 64bits syscall in assembly.
I was writing some code for reading keyboard and simply print it on screen the pressed keys: i'm using sys_read.
The code:
section .text
global _start
_start:
;write startmsg
mov rax, 1
mov rdi, 1
mov rsi, startmsg
mov rdx, sizestart
syscall
;using sys_read
mov ax, 0
mov rdi, 0
mov rsi, key
mov rdx, 2
syscall
;trying to see if esc is pressed then exit
mov rbx, 0x1b
cmp rbx, key
je _exit
_exit:
mov rax, 60
mov rdi, 0
syscall
section .bss
key resw 1
section .data
startmsg db 'Press a key', 10
sizestart equ $-startmsg
Now two things happen: 1) it automatically prints on screen the keys (D:) 2) it doesn't exit when i press esc
回答1:
it automatically prints on screen the keys
This is the default setting in Linux (independent of the programming language):
- Keyboard input is printed to the screen
- sys_read will wait until the return (enter) key is pressed
To change this behaviour the tcsetattr() function (in C) must be called. You should call the tcgetattr() function before to store the current settings and restore them before leaving the program.
If you want to use system calls directly: tcsetattr and tcgetattr both use some sys_ioctl. To find out which ioctl() code is used you may write a C program doing tcsetattr and tcgetattr and use "strace" to find out which syscalls are called.
it doesn't exit when i press esc
There are three problems in the file:
- As far as I understand correctly you read two bytes - which means two keystrokes - whenever you call sys_read
- sys_read will wait until the return key is pressed (see above)
- You compare a 64-bit value to a piece of memory that is only one (or two) byte(s) long.
You should read only one byte using sys_read. Then you should do a bytewise compare instead of a 64-bit compare:
cmp bl,key
instead of:
cmp rbx,key
来源:https://stackoverflow.com/questions/24419077/reading-input-from-keyboard-with-x64-linux-syscalls-assembly