首页 文章

x86架构中的指令解码[关闭]

提问于
浏览
3

我正在为我的实验室开发一个操作系统项目,我在这里从指令指针指向的地址读取数据 . 该数据的第一个字节给出了指令类型 . 例如,如果第一个字节是 0xC6 ,则它是 MOVB 指令 . 现在有些情况下指令指针的第一个字节是 0x0F . 根据文档 0x0F ,这意味着它是一个双字节指令 . 我的问题是这种类型的指令 . 我不知道如何找出双字节指令的指令类型 .

在那之后,我的第二个优先级是两个找出指令的操作数 . 我不知道从代码中做到这一点 . 任何示例代码将不胜感激

第三,需要找出指令的大小 . 由于x86是可变长度,我想知道每个指令的大小 . 起初我打算使用查找表,我将维护指令名称及其大小 . 但后来我发现相同的指令可以有不同的长度 . 例如,当我在 .o 文件上使用对象转储时,我发现了两条指令 C6 00 62 ,这是 MOVB $0x62,(%EAX)C6 85 2C FF FF FF 00 ,这是 MOVB $0x0,-0xD4(%EBP) . 看这里两个指令类型相同( C6 )但是长度不同 .

所以我需要回答这些问题 . 如果有人能给我一些解决方案,我们将非常感激 .

3 回答

  • 1

    另外一种方法是使用众多解析器生成器框架之一(例如无处不在的yacc)为程序集实际构建适当的解析器 . 与使用具有大量案例的嵌套switch语句相比,这可能导致更容易维护和模式可读的实现 .

    还有一种中间方法,因此可以实现基于表的解析器"by hand" . 一个例子在这里:https://github.com/libcpu/libcpu/blob/master/arch/x86/x86_decode.cpp

  • 4

    kvm 有一个非常复杂的x86仿真器/解码器,可以由您的项目重用 .

  • 8

    基本上你需要的是一组嵌套的case语句,实现一个有限状态机扫描器,其中每个级别检查操作码的一些字节(通常是从左到右)以确定它的作用 .

    你的顶级case语句几乎是256个case,每个操作码字节一个;你会发现一些操作码(特别是所谓的“前缀”字节)导致顶层循环(在主操作码字节之前拾取多个前缀字节) . 子案例将根据x86的操作码结构获取结构;你几乎肯定会得到一个MODRM和SIB寻址模式字节解码器/子程序 .

    我做到了这一点;由于细节但工作很烦人,但并不难 . 如果你小心的话,你可以在几百行代码中得到一个很好的解决方案 . 如果你坚持做整个指令集(向量寄存器和操作码,尤其是用于haswell等),你可能会得到更大的东西;英特尔一直在将指令干扰到他们能找到的每个黑暗角落 .

    你真的需要一个操作码映射;我'm pretty sure there is one in the Intel manuals. I'已经发现这个链接非常有用:http://www.ref.x86asm.net/coder32.html

    编辑2015年9月:在这里,我提供了实现此目的的C代码:https://stackoverflow.com/a/23843450/120163

相关问题