使用x86_64 sys_call在Linux上读取单键输入(无需等待返回) [英] Reading a single-key input on Linux (without waiting for return) using x86_64 sys_call
问题描述
我想让linux使用sys_read从键盘上敲击1次键,但是sys_read只是等到按回车键时才可以.如何阅读1击键?这是我的代码:
I want to make linux just take 1 keystroke from keyboard using sys_read, but sys_read just wait until i pressed enter. How to read 1 keystroke ? this is my code:
Mov EAX,3
Mov EBX,0
Mov ECX,Nada
Mov EDX,1
Int 80h
Cmp ECX,49
Je Do_C
Jmp Error
我已经尝试使用BIOS中断,但是失败了(分段错误),我想从键盘捕获1到8的输入.谢谢你的进步 对不起,英语不好
I already tried using BIOS interrupt but it's failed (Segmentation fault), I want capture number 1 to 8 input from keyboard. Thanks for the advance Sorry for bad english
推荐答案
64位linux中的系统调用
man syscall
中的表在此处提供了很好的概述:
Syscalls in 64-bit linux
The tables from man syscall
provide a good overview here:
arch/ABI instruction syscall # retval Notes
──────────────────────────────────────────────────────────────────
i386 int $0x80 eax eax
x86_64 syscall rax rax See below
arch/ABI arg1 arg2 arg3 arg4 arg5 arg6 arg7 Notes
──────────────────────────────────────────────────────────────────
i386 ebx ecx edx esi edi ebp -
x86_64 rdi rsi rdx r10 r8 r9 -
我已省略了此处不相关的行.在32位模式下,参数在eax
, ecx
等中传输,并且系统调用号在eax
中.在64位模式下,情况有所不同:现在所有寄存器均为64位宽,因此具有不同的名称.系统调用号仍在eax
中,现在变为rax
.但是参数现在在rdi
, rsi
等中传递.此外,此处使用指令syscall
代替int 0x80
来触发系统调用.
I have omitted the lines that are not relevant here. In 32-bit mode, the parameters were transferred in eax
, ecx
etc. and the syscall number is in eax
. In 64-bit mode it is a little different: All registers are now 64-bit wide and therefore have a different name. The syscall number is still in eax
, which now becomes rax
. But the parameters are now passed in rdi
, rsi
etc. In addition, the instruction syscall
is used here instead of int 0x80
to trigger a syscall.
参数的顺序也可以在手册页(此处为man 2 ioctl
和man 2 read
)中阅读:
The order of the parameters can also be read in the man pages, here man 2 ioctl
and man 2 read
:
int ioctl(int fd, unsigned long request, ...);
ssize_t read(int fd, void *buf, size_t count);
所以int fd
的值在rdi
中,第二个参数在rsi
中,等等.
So here the value of int fd
is in rdi
, the second parameter in rsi
etc.
首先在内存中创建一个termios
结构(在.bss
部分中):
Firstly create a termios
structure in memory (in .bss
section):
termios:
c_iflag rd 1 ; input mode flags
c_oflag rd 1 ; output mode flags
c_cflag rd 1 ; control mode flags
c_lflag rd 1 ; local mode flags
c_line rb 1 ; line discipline
c_cc rb 19 ; control characters
然后获取当前的终端设置并禁用规范模式:
Then get the current terminal settings and disable canonical mode:
; Get current settings
mov eax, 16 ; syscall number: SYS_ioctl
mov edi, 0 ; fd: STDIN_FILENO
mov esi, 0x5401 ; request: TCGETS
mov rdx, termios ; request data
syscall
; Modify flags
and byte [c_cflag], $FD ; Clear ICANON to disable canonical mode
; Write termios structure back
mov eax, 16 ; syscall number: SYS_ioctl
mov edi, 0 ; fd: STDIN_FILENO
mov esi, 0x5402 ; request: TCSETS
mov rdx, termios ; request data
syscall
现在,您可以使用sys_read
来读取按键:
Now you can use sys_read
to read in the keystroke:
mov eax, 0 ; syscall number: SYS_read
mov edi, 0 ; int fd: STDIN_FILENO
mov rsi, buf ; void* buf
mov rdx, len ; size_t count
syscall
然后检查rax
中的返回值:它包含读取的字符数.
Afterwards check the return value in rax
: It contains the number of characters read.
参考:
- 为什么sys_read系统调用检测到新行时会结束吗?
- 如何.我如何在ubuntu下使用nasm(汇编)从键盘读取单个字符输入?.
- 在Linux下使用原始键盘模式(外部站点,例如32-位组装)
- Why does the sys_read system call end when it detects a new line?
- How do i read single character input from keyboard using nasm (assembly) under ubuntu?.
- Using the raw keyboard mode under Linux (external site with example in 32-bit assembly)
这篇关于使用x86_64 sys_call在Linux上读取单键输入(无需等待返回)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!