x86反汇编程序如何知道在哪里分解指令?
我正在查看8088指令集.例如,移动指令有7种变化,范围从2到4个字节.说明本身似乎没有遵循特定的顺序.为什么x86难看的另一个原因是什么?.
例如:
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)
Run Code Online (Sandbox Code Playgroud)
许多指令可以在第一个字节中重叠:
76543210 76543210 76543210 76543210
push 11111111 ||110r/m
inc 1111111w ||000r/m
Run Code Online (Sandbox Code Playgroud)
位掩码似乎具有任意分配.拆卸器如何拆分指令?
查看我的8086/8088用户手册程序员参考(ISBN 1-55512-010-5),可能已有数十年的绝版...附录A显示了以操作码顺序0b00000000到0b11111111的指令解码.看起来一点也不混乱.添加,子和,xor,cmp等都以这样的方式分组,即多路复用器可以直接使用操作码位来路由输入和输出,而其他位选择alu对这些位执行的操作.
对于编写反汇编程序,您希望使用此类表或操作码图表进行顶级的指令排序.
在您的特定示例中,请注意每当您将第一个操作码视为0xFF时,在第二个字节的中间有三个位,它们告诉您故事的其余部分是哪个指令.这些组合中的所有8个(一个未定义)被表示并且容易从这3个位解码.
是的,x86指令集很疯狂.有趣和有趣的功能,但从那以后发明了相当好的指令集.例如,x86没有走过6502的唯一原因是动力,而不是质量.
你也应该看看这个:
如何反汇编这个和任何其他变量字长指令集是按执行顺序进行的.如果您尝试按地址顺序线性执行,则会失败.从向量表开始获取入口地址,然后按地址顺序按照这些说明进行操作,记下并跟踪所有分支,直到您点击无条件分支或返回或终止该指令串的其他指令.对每个分支目的地重复此操作.这不会涵盖所有可能的指令,因为代码可能会在执行时计算地址(您可以做很多关于拆卸的地址).
如果这些代码中的任何一个是有意或无意地手写的,以便使反汇编程序绊倒,则可能会发生冲突,其中基于一个执行路径的一个操作码的第二个或第三个字节似乎是基于不同执行的指令的第一个操作码路径.例如,清除标志指令后跟条件分支(如果标志清除),后跟数据字节,后跟真实指令,即分支目的地.是的,我遇到过这个.并且它应该被你的反汇编程序困住,你需要在它们发生碰撞时放入检查以停止拆解其中一条或两条执行路径.对于完整的反汇编,期望必须支持某种用户输入以将地址排除为操作码,以及用户手动添加有效的操作码以便您遵循执行路径.
对于固定长度的指令集,您可以轻松地在地址或执行顺序中进行反汇编,您的选择,地址顺序从0到内存结束当然是最简单的.不要在未定义的指令上输出错误,只需将它们标记为原样并继续运行,其中一些是数据.
x86绝对是我试图反汇编的最后一个可变长度指令集,我写了很多反汇编程序.不想尝试这个项目.从一些固定长度的开始,如pic和arm/thumb.尝试msp430的可变字长,然后可能是6502(小行星,小行星豪华,月球着陆器等).也许一周或两个晚上的时间来覆盖上面并获得它的感觉,然后攻击x86如果欲望仍然存在.如果你严格限制在8088/8086,那就不是那么糟糕,需要确保你的工具正在生成这些指令,而不是进入386的指令.
如果push vs inc困扰你,那么首先要尝试像msp430这样的其他东西.
| 归档时间: |
|
| 查看次数: |
1851 次 |
| 最近记录: |