【问题标题】:Keyboard handler causes segfault (djgpp)键盘处理程序导致段错误(djgpp)
【发布时间】:2016-06-23 16:10:08
【问题描述】:

最近我决定编写一些简单的 MSDOS 游戏,这很有趣。不用说,我需要处理键盘事件的代码。

这是我想出的测试:

int i, c = 0;
for ( i = 0; i < 10; i++ )
{
    asm
    (
        "mov $0x00, %%ah         \n"
        "mov $0x00, %%al         \n"
        "int $0x16               \n"
        //"jnz keydn             \n"
        //"mov $0x00, %%al       \n"
        //"keydn:                \n"
        "movw %%ax, (%0)         \n"
            : "=r"(c)
    );

    printf( "%d\n", c & 0xFF );
}

代码应该等待按键,然后打印出字符的 ASCII 值。 除非我按 backspaceesc 之类的键,否则一切都会按预期工作 - 然后会发生分段错误。

我不熟悉组装,但我真的无法弄清楚可能导致此错误的原因。

我使用djgpp 编译,并在DosBox 中运行可执行文件

一切都基于此处提供的信息:

提前感谢您! :)

【问题讨论】:

  • "mov $0x00, %%ah\n" "mov $0x00, %%al\n" 可以替换为"xor %%ax, %%ax\n" 或更好,但使用输入操作数将0 传递到模板中(寄存器a 可以成为输入和输出操作数) .这将消除模板本身将 AX 寄存器归零的需要。
  • @MichaelPetch 对,我明白它是如何工作的,但正如我之前所说,我以前从未使用过裸组装,所以我想让一切尽可能简单。无论如何,它会提高执行速度还是什么?
  • 是的,如果您为受限的内存环境编写代码,则需要更少的内存字节进行编码。
  • @MichaelPetch 我明白了。根据我今天的经验,我可以看到,即使是组装基础也相当棘手。无论如何,我认为在这种情况下我不需要一些出色的性能,至少在键盘处理程序中,因为我使用的系统计时器以 18.2Hz 运行,这真的很慢。当它通过软盘在真正的 PC 上运行时,我会将整个过程视为成功;)
  • 这个问题:stackoverflow.com/questions/421860/…> 对您的问题有几个有效的、可移植的答案。

标签: c assembly segmentation-fault dos djgpp


【解决方案1】:

这肯定坏了:movw %%ax, (%0): "=r"(c) 它尝试将操作数 0 给定的地址写入内存,该地址是输出操作数,因此未初始化。它也不是指针。您可能想要执行以下操作:

   asm
    (
        "mov $0x00, %%ah         \n"
        "mov $0x00, %%al         \n"
        "int $0x16               \n"
            : "=a"(c)
     );

PS:学习使用调试器或至少将寄存器转储与您的代码交叉引用。

【讨论】:

  • 谢谢!它解决了这个问题,现在就像一个魅力 :) 不幸的是,我不熟悉 DOS 调试器之类的东西,不过我会努力提高我可怜的汇编技能
猜你喜欢
  • 1970-01-01
  • 2011-09-16
  • 1970-01-01
  • 2014-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-02
  • 1970-01-01
相关资源
最近更新 更多