การอ่านอินพุตจากแป้นพิมพ์ด้วย x64 linux syscalls (ชุดประกอบ)

ฉันกำลังพยายามเรียนรู้วิธีใช้ linux 64bits syscall ในแอสเซมบลี

ฉันกำลังเขียนโค้ดสำหรับอ่านคีย์บอร์ดและพิมพ์บนหน้าจอเมื่อกดปุ่ม: ฉันใช้ sys_read

รหัส:

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

ตอนนี้มีสองสิ่งเกิดขึ้น: 1) มันจะพิมพ์ปุ่มบนหน้าจอโดยอัตโนมัติ (D :) 2) มันจะไม่ออกเมื่อฉันกด esc


person vMind    schedule 25.06.2014    source แหล่งที่มา


คำตอบ (1)


มันจะพิมพ์ปุ่มบนหน้าจอโดยอัตโนมัติ

นี่เป็นการตั้งค่าเริ่มต้นใน Linux (ไม่ขึ้นอยู่กับภาษาการเขียนโปรแกรม):

  • การป้อนข้อมูลด้วยแป้นพิมพ์จะถูกพิมพ์ลงบนหน้าจอ
  • sys_read จะรอจนกว่าจะกดปุ่ม return (enter)

หากต้องการเปลี่ยนพฤติกรรมนี้ จะต้องเรียกใช้ฟังก์ชัน tcsetattr() (ในภาษา C) คุณควรเรียกใช้ฟังก์ชัน tcgetattr() ก่อน เพื่อจัดเก็บการตั้งค่าปัจจุบันและกู้คืนการตั้งค่าก่อนออกจากโปรแกรม

หากคุณต้องการใช้การเรียกของระบบโดยตรง: tcsetattr และ tcgetattr ทั้งคู่ใช้ sys_ioctl บางตัว หากต้องการทราบว่ารหัส ioctl() ใดที่ใช้อยู่ คุณอาจเขียนโปรแกรม C โดยใช้ tcsetattr และ tcgetattr และใช้ "strace" เพื่อค้นหาว่า syscalls ใดถูกเรียก

มันไม่ออกเมื่อฉันกด esc

มีปัญหาสามประการในไฟล์:

  1. เท่าที่ฉันเข้าใจถูกต้องคุณอ่านสองไบต์ - ซึ่งหมายถึงการกดแป้นพิมพ์สองครั้ง - เมื่อใดก็ตามที่คุณเรียก sys_read
  2. sys_read จะรอจนกว่าจะกดปุ่ม return (ดูด้านบน)
  3. คุณเปรียบเทียบค่า 64 บิตกับชิ้นส่วนของหน่วยความจำที่มีความยาวเพียงหนึ่ง (หรือสอง) ไบต์

คุณควรอ่านเพียงหนึ่งไบต์โดยใช้ sys_read จากนั้นคุณควรทำการเปรียบเทียบแบบไบต์แทนการเปรียบเทียบแบบ 64 บิต:

cmp bl,key

แทน:

cmp rbx,key
person Martin Rosenau    schedule 26.06.2014