x86汇编:反汇编程序如何知道如何分解指令?

时间:2010-10-21 01:54:24

标签: assembly x86 disassembly

x86反汇编程序如何知道在哪里分解指令?

我正在查看8088指令集。例如,移动指令有7种变化,范围从2到4个字节。说明本身似乎没有遵循特定的顺序。 Why is x86 ugly?的另一个原因。

例如:

                        76543210  76543210  76543210  76543210
reg/mem to/from reg     100010dw  ||regr/m  
imm to reg/mem          1100011w  ||000r/m  dat       dat w=1
imm to reg              1011wreg  data      dat w=1
imm to accum            1010000w  addr-low  addrhigh
accum to mem            1010001w  addr-low  addrhigh
reg/mem to seg          10001100  ||0ssr/m
seg to reg/mem          10001100  ||0ssr/m

Legend:
||=mod {NO-DISP=0,DISP-LOW,DISP-HIGH,REG}
ss=seg enum{es=0,cs,ss,ds}
reg=enum{ax=0,bx,cd,dx,bx,sp,bp,si,di (if w=1)} enum{al,bl...} (if w=0)
r/m=reg or mem (mod=3 then REG, else mem)

许多指令可以在第一个字节中重叠:

                        76543210  76543210  76543210  76543210
push                    11111111  ||110r/m
inc                     1111111w  ||000r/m

位掩码似乎具有任意分配。拆卸器如何拆分指令?

此问题是How to write a disassembler.

的子集

1 个答案:

答案 0 :(得分:8)

查看我的8086/8088用户手册程序员参考(ISBN 1-55512-010-5),可能已有数十年的绝版...附录A显示了以操作码顺序0b00000000到0b11111111的指令解码。看起来一点也不混乱。添加,子和,xor,cmp等都以这样的方式分组,即多路复用器可以直接使用操作码位来路由输入和输出,而其他位选择alu对这些位执行的操作。

对于编写反汇编程序,您希望使用此类表或操作码图表进行顶级的指令排序。

在您的特定示例中,请注意每当您将第一个操作码视为0xFF时,在第二个字节的中间有三个位,它们告诉您故事的其余部分是哪个指令。这些组合中的所有8个(一个未定义)都被表示,并且可以从这3个位中轻松解码。

是的,x86指令集很疯狂。有趣和有趣的功能,但从那以后发明了相当好的指令集。例如,x86没有像6502那样走的唯一原因是动量,而不是质量。

你也应该看一下这个:

How are hex sequence translated to assembly without ambiguity?

如何对此和任何其他可变字长指令集进行反汇编是按执行顺序进行的。如果您尝试按地址顺序线性执行,则会失败。从向量表开始获取入口地址,然后按地址顺序按照这些说明进行操作,记下并跟踪所有分支,直到您点击无条件分支或返回或终止该指令串的其他指令。对每个分支目的地重复此操作。这不会涵盖所有可能的指令,因为代码可能会在执行时计算地址(您可以做很多关于拆卸的地址)。

如果这些代码中的任何一个是有意或无意地手写的,以便使反汇编程序绊倒,那么基于一个执行路径的一个操作码的第二个或第三个字节似乎是基于一个指令的第一个操作码的冲突不同的执行路径。例如,清除标志指令后跟条件分支(如果标志清除),后跟数据字节,接着是作为分支目的地的实际指令。是的,我遇到过这个。并且它应该被你的反汇编程序困住,你需要在它们发生碰撞时放入检查以停止拆解其中一条或两条执行路径。对于完整的反汇编,期望必须支持某种用户输入以将地址排除为操作码,以及用户手动添加有效的操作码以便您遵循执行路径。

对于固定长度指令集,您可以轻松地在地址或执行顺序中进行反汇编,您的选择,地址顺序从0到内存结束当然是最简单的。不要在未定义的指令上输出错误,只需将它们标记为原样并继续运行,其中一些是数据。

x86绝对是我试图反汇编的LAST可变长度指令集,我编写了许多反汇编程序。不想尝试这个项目。从一些固定长度的开始,如pic和arm / thumb。尝试msp430的可变字长,然后可能是6502(小行星,小行星豪华,月球着陆器等)。可能需要一两个星期的晚上才能覆盖上面并获得它的感觉,然后如果欲望仍然存在则攻击x86。如果你严格限制在8088/8086,那就不是那么糟糕,需要确保你的工具正在生成这些指令,而不是进入386的指令。

如果push vs inc困扰你,那么首先要尝试像msp430这样的其他东西。