【问题标题】:Linux asm - int 16h analogue to read raw keyboard scancodesLinux asm - int 16h 模拟读取原始键盘扫描码
【发布时间】:2019-04-26 09:52:37
【问题描述】:

为了我的学习,我需要在asm上写一个程序,它会等到键盘按键被按下,然后打印它的扫描码和按键字符的ASCII码。

我知道 BIOS 的 int 16h 可以完成这项工作,但我现在使用的是 Linux,找不到合适的模拟系统调用。

我应该用什么来完成这项任务?我目前正在为我的汇编代码使用 Debian Stretch 和 NASM。

【问题讨论】:

  • 这并不容易,因为键盘离您的程序有好几层抽象。对于控制台应用程序,最简单的方法是首先将终端设置为无缓冲模式,然后读取单个字符。这有点烦人,但在组装时是可行的。
  • 另一种可能导致代码更简单但执行准备工作更复杂的方法是编写一个仅使用int 16h(和其他适当的 BIOS 功能)的实模式程序,将其编译为一个独立的二进制文件,并将其安装在 PC 的引导加载程序(通常是 GRUB)可以找到并执行它的地方。为了进行测试,您可以运行虚拟 PC 并使用虚拟引导加​​载程序来运行您的二进制文件。
  • 您也许可以为此使用“输入”子系统。见man input-events

标签: linux assembly keyboard nasm scancodes


【解决方案1】:

通常,内核将键盘扫描码转换为您可以在 tty 上读取的 ASCII 字符。但是有一些方法可以获得原始扫描码,例如看看showkey(1) 在文本控制台上是如何做到的 (http://kbd-project.org/)。 https://wiki.archlinux.org/index.php/Keyboard_input

https://github.com/legionus/kbd/blob/2.0.4/src/showkey.c 表明您可以在控制台终端的文件描述符上使用ioctl(2) 将 KBD 转换模式设置为 RAW(扫描码)或 MEDIUMRAW(键码)。然后就可以进行正常的read系统调用了。

ioctl(fd, KDSKBMODE, show_keycodes ? K_MEDIUMRAW : K_RAW)

显然,您可以使用 x86-64 上的 syscall 或 32 位 x86 上的 int 0x80 从手写 asm 进行这些系统调用,在 asm/unistd_64.h 中查找系统调用号,并在它们各自的标题。


showkey 会注意设置一个看门狗定时器以干净地退出并捕获信号,因为这样做会在内核处理 control-C 或 ctrl+alt+f2 之前拦截键序列。因此,如果没有超时,就无法退出程序。如果你在没有恢复正常模式的情况下退出,将无法在控制台上键入运行命令来恢复正常键盘模式。

【讨论】:

  • 请注意,这仅适用于虚拟控制台,不适用于终端模拟器。
猜你喜欢
  • 2023-03-30
  • 2014-09-19
  • 2022-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-18
  • 2015-03-16
相关资源
最近更新 更多