[英]Wait for keypress Assembly NASM, Linux
我正在为x86-64组装Hello World。
我设法创建了一个在按下Enter键时完成的操作,但是在按下ANY键时必须完成操作。
这是等待ENTER键的代码:
mov rax, 0
mov rdi, 0
mov rdx, 1
syscall
我不能使用任何int xh或类似的东西。 仅系统调用。
谢谢!
之前 ,我已经回答了类似的问题 ,并提供了可直接与系统调用配合使用以执行所需操作的C代码。
这是该代码到nasm的翻译,稍作更改以反映您只是在检查是否已按下任何键,而不是特定键:
fwait:
; fetch the current terminal settings
mov rax, 16 ; __NR_ioctl
mov rdi, 0 ; fd: stdin
mov rsi, 21505 ; cmd: TCGETS
mov rdx, orig ; arg: the buffer, orig
syscall
; again, but this time for the 'new' buffer
mov rax, 16
mov rdi, 0
mov rsi, 21505
mov rdx, new
syscall
; change settings
and dword [new+0], -1516 ; ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON)
and dword [new+4], -2 ; ~OPOST
and dword [new+12], -32844 ; ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN)
and dword [new+8], -305 ; ~(CSIZE | PARENB)
or dword [new+8], 48 ; CS8
; set settings (with ioctl again)
mov rax, 16 ; __NR_ioctl
mov rdi, 0 ; fd: stdin
mov rsi, 21506 ; cmd: TCSETS
mov rdx, new ; arg: the buffer, new
syscall
; read a character
mov rax, 0 ; __NR_read
mov rdi, 0 ; fd: stdin
mov rsi, char ; buf: the temporary buffer, char
mov rdx, 1 ; count: the length of the buffer, 1
syscall
; reset settings (with ioctl again)
mov rax, 16 ; __NR_ioctl
mov rdi, 0 ; fd: stdin
mov rsi, 21506 ; cmd: TCSETS
mov rdx, orig ; arg: the buffer, orig
syscall
ret
基本思想是,您必须编辑终端设置,读取字符并重置设置。
我对Cel Skeggs的答案中的代码做了一些修改。
这是一个完整的程序,可以一次打印一个读取键,然后在ENTER上退出。
;; Simple Keyboard Reading in x86_64 assembly, using Linux syscalls
;;
;; nasm -felf64 -o readKey64.o readKey64.asm
;; ld readKey64.o -o readKey64
;; ./readKey64
;;
;; Adaptation of original code from:
;; https://stackoverflow.com/questions/32193374/wait-for-keypress-assembly-nasm-linux
;--------------------------------------------------------------------------
global _start:
section .data
orig: times 10000 db 0 ; reserve way more space than we need for TCGETS
new: times 10000 db 0
char: db 0,0,0,0,0
msg1: db "Reading Keyboard... push ENTER to finish",0ah,0
msglen equ $ - msg1
msg2: db 0ah,"END.",0ah,0
msg2len: equ $ - msg2
section .text
_start:
mov rsi,msg1
mov rax,1
mov rdi,1
mov rdx,msglen
syscall
; fetch the current terminal settings
mov rax, 16 ; __NR_ioctl
mov rdi, 0 ; fd: stdin
mov rsi, 21505 ; cmd: TCGETS
mov rdx, orig ; arg: the buffer, orig
syscall
; again, but this time for the 'new' buffer
mov rax, 16
mov rdi, 0
mov rsi, 21505
mov rdx, new
syscall
; change settings
and dword [new+0], -1516 ; ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON)
and dword [new+4], -2 ; ~OPOST
and dword [new+12], -32844 ; ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN)
and dword [new+8], -305 ; ~(CSIZE | PARENB)
or dword [new+8], 48 ; CS8
; set settings (with ioctl again)
mov rax, 16 ; __NR_ioctl
mov rdi, 0 ; fd: stdin
mov rsi, 21506 ; cmd: TCSETS
mov rdx, new ; arg: the buffer, new
syscall
.readchar:
; read a character
mov rax, 0 ; __NR_read
mov rdi, 0 ; fd: stdin
mov rsi, char ; buf: the temporary buffer, char
mov rdx, 1 ; count: the length of the buffer, 1
syscall
mov rax,1 ; __NR_write
mov rdi,1
mov rdx,1
syscall ; sys_write(1, char, 1) // RSI is still set to buf
cmp byte[char],13
jz .end
jmp .readchar
.end:
; reset settings (with ioctl again)
mov rax, 16 ; __NR_ioctl
mov rdi, 0 ; fd: stdin
mov rsi, 21506 ; cmd: TCSETS
mov rdx, orig ; arg: the buffer, orig
syscall
mov rsi,msg2
mov rax,1
mov rdi,1
mov rdx,msg2len
syscall ; sys_write(1, msg2, msg2len)
mov rax,60
mov rdi,0
syscall ; sys_exit(0)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.