组装键盘IO口

Bar*_*rak 5 keyboard x86 assembly

我看过以下主题

我有兴趣通过 IN / OUT 指令联系键盘并设置各种模式,例如打开大写锁定 LED。到目前为止,我在这样做时遇到了问题。以下链接可能会有所帮助。

我尝试了各种组合,例如

mov al,0EDh           ;ED command - Send LED bits. The next byte written to port 60h updates the LEDs on the keyboard.
out 60h,al            ;out on port 60h
mov al,00000111b      ;led status - all leds on. bits 3-7 = reserved(zero)
out 60h,al            ;out on port 60h
Run Code Online (Sandbox Code Playgroud)

我将不胜感激任何帮助。谢谢。

编辑:正如我所说,使用端口 60h 不起作用我在网上搜索了 0040:0017 的用法。其中一个网站指出,第 5、6、7 位包含有关 LED 状态的数据

我尝试使用此代码:

mov al,es:[0017h]
or al,11100000b
mov es:[0017h],al
Run Code Online (Sandbox Code Playgroud)

它也不起作用。

我可能做错了,所以任何人都可以帮助我或向我发送打开所有 3 个 LED 的工作代码吗?

EDIT2:我在安装在 VM 上的 MS-DOS 上运行我的应用程序,代码运行良好。

我的问题是:我怎样才能让它在 MS-DOS 之外工作?

nin*_*alj 3

要从在 VM86 模式或保护模式下运行的任务访问 I/O 端口,您需要特殊权限。此特权可以通过以下方式获得:

  • IOPL(仅适用于保护模式任务):如果任务的当前权限级别<=任务的IOPL,则允许访问。
  • I/O 权限位图(对于 VM86 任务和 CPL 不足的保护模式任务):TSS 可能包含用于允许/拒绝 I/O 端口访问的位图。

当访问被拒绝时,会生成 GPF。

Linux 具有 iopl() 和 ioperm() 系统调用,允许具有 CAP_SYS_RAWIO 的进程获取这些权限。因此,在 Linux 上访问键盘 LED 可以这样完成:

#include <stdio.h>
#include <sys/io.h>

int main()
{
    int ret;

    ret = ioperm(0x60, 0xf, 1);
    if (ret < 0) {
            perror("ioperm");
            return 1;
    }
    while (inb(0x64) & 0x2);
    outb(0xed, 0x60);
    while (inb(0x64) & 0x2);
    outb(0x07, 0x60);
    ioperm(0x60, 0xf, 0);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Windows NTVDM和Linuxosemu使用VM86模式来运行实模式DOS程序。当尝试进行不允许的 I/O 端口访问时,会生成 GPF,并且这些系统可以模拟(或不模拟)I/O 端口访问。osemu 有一个 -k 开关,可以绕过通常的 tty 层并直接访问键盘。使用这个开关你的第一个例子就可以工作了。

现在,要在 Windows 上执行相同的操作,可能需要从在环 0 上运行的驱动程序执行此操作。替代方案可能是使用允许环 3 进程访问 I/O 端口的驱动程序(非常不安全):例如,请参阅ioperm对于 cygwin