首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用x86_64 sys_call读取Linux上的单键输入(不等待返回)

问使用x86_64 sys_call读取Linux上的单键输入(不等待返回)
EN

Stack Overflow用户
提问于 2020-07-16 14:37:22
回答 1查看 1K关注 0票数 1

我想让Linux使用sys_read从键盘上敲击1下键,但是sys_read只是等待直到我按enter键。怎么看1击键?这是我的密码:

代码语言:javascript
复制
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输入。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-16 16:59:20

64位linux中的Syscalls

man syscall的表在这里提供了一个很好的概述:

代码语言:javascript
复制
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位模式下,参数以ebx、ecx等方式传输,syscall数在eax中传输.在64位模式下,这有点不同:所有寄存器现在都是64位宽,因此有一个不同的名称。syscall号仍然在eax中,现在它变成了rax。但是现在参数在rdi、rsi等中传递。此外,这里使用指令syscall而不是int 0x80来触发syscall。

参数的顺序也可以在手册页中读取,这里是man 2 ioctl和man 2 read

代码语言:javascript
复制
int ioctl(int fd, unsigned long request, ...);
ssize_t read(int fd, void *buf, size_t count);

在这里,int fd的值在rdi中,第二个参数在rsi中,等等。

如何摆脱等待换线的等待

首先在内存中创建一个termios结构(在.bss部分):

代码语言:javascript
复制
termios:
  c_iflag resd 1   ; input mode flags
  c_oflag resd 1   ; output mode flags
  c_cflag resd 1   ; control mode flags
  c_lflag resd 1   ; local mode flags
  c_line  resb 1   ; line discipline
  c_cc    resb 19  ; control characters

然后获取当前终端设置并禁用规范模式:

代码语言:javascript
复制
; 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_lflag], 0FDh  ; 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在击键时读取:

代码语言:javascript
复制
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中的返回值:它包含读取的字符数。

(错误码,例如,如果您在bash中运行./a.out <&-来关闭stdin )。使用strace打印系统调用您的程序的解码跟踪,因此您不需要在玩具实验中实际编写错误处理。

参考资料:

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62937150

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档