x86架构中的指令解码

azi*_*kim 3 c c++ x86 assembly decode

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

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

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

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

Ira*_*ter 9

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

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

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

你真的需要一个操作码映射; 我很确定英特尔手册中有一个.我发现这个链接非常有用:http://www.ref.x86asm.net/coder32.html

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

  • @ user16653:有时邪恶是正确的事:) (5认同)
  • ... EIP-> 0F 00 .. 0F是LOCK或REPNE前缀字节.整个事情看起来有点像"LOCK ADD modrm ..."我没有解码modrm部分; 你可以做到这一点. (2认同)

oak*_*kad 5

另一种方法是使用许多解析器生成器框架之一(例如无处不在的yacc)为组装实际构建一个适当的解析器。与在大量情况下使用嵌套的switch语句相比,这可能导致维护和模式可读的实现更容易。

还有一种中间方法,基于表的解析器可以“手动”实现。一个示例在这里:https : //github.com/libcpu/libcpu/blob/master/arch/x86/x86_decode.cpp