我正在为我的实验室做一个操作系统项目,在那里我要使用指令指针和指令操作码。现在我只需要知道它是什么类型的指令。为此,我从指令指针指向的地址读取数据。该数据的第一个字节给出了指令类型。例如,如果第一个字节是0xC6
,那么它就是MOVB
指令。现在有些情况下,指令指针的第一个字节是0x0F
。根据文档0x0F
,这意味着它是一个两个字节的指令。我的问题是这类指令。我不知道如何找出两个字节指令的指令类型。
在那之后,我的第二个优先级是两个,找出指令的操作数。我不知道用代码来做这件事。任何示例代码都将不胜感激。
第三,需要找出指令的大小。由于x86是可变长度的,所以我想知道每个指令的大小。起初,我计划使用一个查找表,在那里我将维护指令名和它的大小。但是后来我发现相同的指令可以有可变的长度。例如,当我对一个.o
文件使用对象转储时,我发现了两个指令C6 00 62
,它用于MOVB $0x62,(%EAX)
& C6 85 2C FF FF FF 00
,用于MOVB $0x0,-0xD4(%EBP)
。看这里,这两种指令类型是相同的(C6
),但长度不同。
所以我需要这些问题的答案如果有人能给我一些解决办法,我会非常感激的。
发布于 2013-12-02 02:06:29
基本上,您需要的是一组嵌套的case语句,实现一个有限状态机扫描器,其中每个级别检查操作码的一些字节(通常是从左到右),以确定它所做的事情。
顶级case语句将几乎是256种情况,每个操作码字节一种;您会发现一些操作码(特别是所谓的“前缀”字节)导致顶层循环(在主opcode字节之前拾取多个前缀字节)。子案例将根据x86的操作码结构获得结构;您几乎肯定会得到一个MODRM和SIB寻址模式、字节解码器/子例程。
我已经做过这件事了;这件工作很烦人,因为细节问题,但并不难。如果你小心的话,你可以在几百行代码中得到一个很好的解决方案。如果你坚持做整个指令集(矢量寄存器和操作码,尤指。(为haswell等)你可能最终会得到更大的东西;英特尔一直在干扰他们能找到的每一个黑暗角落的指令。
你真的需要一个操作码地图;我很确定英特尔手册中有一个。我发现这个链接非常有用:http://www.ref.x86asm.net/coder32.html
编辑2015年9月:在这里,我提供了实现以下内容的C代码:https://stackoverflow.com/a/23843450/120163
发布于 2013-12-02 04:14:18
另外一种方法是使用许多解析器生成器框架(如无处不在的yacc)之一,为程序集实际构建一个合适的解析器。这可能比使用具有大量情况的嵌套开关语句更易于维护和模式可读的实现。
还有一种中间方法,基于表的解析器可以“手工”实现。这里有一个例子:decode.cpp
发布于 2013-12-02 04:29:40
kvm
有一个非常复杂的x86仿真器/解码器,您的项目可以重用它。
https://stackoverflow.com/questions/20319704
复制相似问题