使用x86_64 sys_call在Linux上读取单键输入(无需等待返回) [英] Reading a single-key input on Linux (without waiting for return) using x86_64 sys_call

查看:143
本文介绍了使用x86_64 sys_call在Linux上读取单键输入(无需等待返回)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想让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 ioctlman 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.

参考:

  • 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆