x86解码指令操作码字节

时间:2017-09-14 23:42:27

标签: data-structures x86 disassembly opcode mnemonics

我正在创建一个x86解码器,并且我正在努力理解并找到一种有效的方法来计算指令的助记符。

我知道操作码6 MSB是操作码位,但我找不到在助记符表中使用这6位的任何地方。我找到的唯一助记符表是整个操作码字节本身而不仅仅是6个MSB。

我想问一下有什么方法可以解码操作码字节中编码的助记符,以及使用6个MSB而不是整个操作码字节的任何表引用。

1 个答案:

答案 0 :(得分:1)

  

但是,是否有一种有效的方法来存储没有重复的助记符表?

这已成为算法和数据结构的问题。

正如您所指出的,许多操作码表条目(至少对于没有0f转义字节的表:http://sparksandflames.com/files/x86InstructionChart.html)确实以4或2的组重复,即具有相同的6或7位前缀选择相同的助记符。

显然,256条结构表很简单,但重复一点。它非常快速且易于使用,因为它可能仍然很小,不会经常出现缓存缺失。 (特别是因为公共条目在缓存中保持热; x86代码使用相同的操作码。)

您可以为空间交换简单/性能。

你可以有一个64项的结构表,其中一个成员是一个指向要用低2位索引的辅助表的指针。如果指针为NULL,则表示该指令遵循add / and / xor /等模式,其中低2位告诉您8位与操作数大小无关是和方向(r / m,reg或reg,r / m)。

当某些前缀存在时,您的结构还需要输入其他指令的条目(例如rep noppause)。此外,AVX VEX前缀使用以前是另一条指令的无效编码。如果你想为所有当前的扩展做一个完整的工作,x86很难解码。

实际上,使用函数指针表可能是最简单的(也是有效的)。或者具有const char* mnemonicint (*decode)(const char*mnemonic, const char *insn_bytes, unsigned prefix_bitmap)函数的结构,因此许多操作码可以指向相同的解码函数但仍然获得不同的助记符。有时函数会忽略传递的助记符,但有时会忽略它所需要的全部内容。您具有解码许多解码函数可以调用的寻址模式的通用功能。

这与您如何实现解释而不是进行动态重新编译的x86模拟器非常相似。一个常见的解码循环,然后通过函数指针调度。

您可能使用的更复杂的数据结构是radix trie aka前缀树。另请参阅https://en.wikipedia.org/wiki/Trie#Bitwise_tries

这进入了愚蠢的季节,因为密度非常高,查找表更有意义。 (很少有未定义的操作码)。