我有兴趣将x86解析器编写为教育项目 .
我发现的唯一真实资源是Spiral Space,“How to write a disassembler” . 虽然这给出了反汇编程序的各种组件的高级描述,但我也快速查看了NASM's源代码,但这有点重要 .
我意识到这个项目的一个主要挑战是我将要处理的相当大的x86指令集 . 我也对基本结构,基本反汇编链接等感兴趣 .
有人能指出我有关编写x86反汇编程序的任何详细资源吗?
我有兴趣将x86解析器编写为教育项目 .
我发现的唯一真实资源是Spiral Space,“How to write a disassembler” . 虽然这给出了反汇编程序的各种组件的高级描述,但我也快速查看了NASM's源代码,但这有点重要 .
我意识到这个项目的一个主要挑战是我将要处理的相当大的x86指令集 . 我也对基本结构,基本反汇编链接等感兴趣 .
有人能指出我有关编写x86反汇编程序的任何详细资源吗?
5 回答
看看80386 Programmer's Reference Manual的section 17.2 . 一个反汇编真的只是一个美化的finite-state machine . 反汇编的步骤是:
检查当前字节是否为指令前缀字节(
F3
,F2
或F0
);如果是这样,那么你有一个REP
/REPE
/REPNE
/LOCK
前缀 . 前进到下一个字节 .检查当前字节是否为地址大小字节(
67
) . 如果是,如果当前处于32位模式,则以16位模式解码其余指令中的地址;如果当前处于16位模式,则解码32位模式下的地址检查当前字节是否为操作数大小字节(
66
) . 如果是,如果当前处于32位模式,则以16位模式解码立即操作数,如果当前处于16位模式,则解码32位模式下的立即操作数检查当前字节是否为段覆盖字节(
2E
,36
,3E
,26
,64
或65
) . 如果是,请使用相应的段寄存器来解码地址而不是默认的段寄存器 .下一个字节是操作码 . 如果操作码是
0F
,则它是扩展操作码,并将下一个字节读作扩展操作码 .根据特定操作码,读入并解码Mod R / M字节,Scale Index Base(SIB)字节,位移(0,1,2或4字节)和/或立即值(0, 1,2或4个字节) . 这些字段的大小取决于操作码,地址大小覆盖和先前解码的操作数大小覆盖 .
操作码告诉您正在执行的操作 . 操作码的参数可以从Mod R / M,SIB,位移和立即值的值解码 . 由于x86的复杂性,有很多可能性和许多特殊情况 . 有关更详细的说明,请参阅上面的链接 .
我建议检查一些开源的反汇编程序,最好是distorm,特别是"disOps (Instructions Sets DataBase)"(ctrl在页面上找到它) .
文档本身充满了关于操作码和指令的丰富信息 .
引自https://code.google.com/p/distorm/wiki/x86_x64_Machine_Code
数据结构和解码阶段在https://code.google.com/p/distorm/wiki/diStorm_Internals中解释
引用:
每个步骤也都有解释 .
原始链接由于历史原因而保留:
http://code.google.com/p/distorm/wiki/x86_x64_Machine_Code和http://code.google.com/p/distorm/wiki/diStorm_Internals
从一些已组装的小程序开始,它既为您提供生成的代码,也为您提供指令 . 使用instruction architecture获取参考,并完成一些生成的工作手工编写带有体系结构参考的代码 . 你会发现这些指令有一个非常定型的inst op op op结构,它有不同数量的操作数 . 您需要做的就是翻译代码的十六进制或八进制表示以匹配指令;一点点玩都会揭示它 .
这个过程是自动化的,是反汇编程序的核心 . 理想情况下,您可能希望在内部(或外部,如果程序非常大)构建n个指令结构数组 . 然后,您可以将该数组转换为汇编程序格式的指令 .
您需要一个可加载的操作码表 .
基本的查找数据结构是一个特里,但如果你不太关心速度,那么表格就可以做得很好 .
要获得基本操作码类型,请从表格开始匹配 .
有一些解决寄存器参数的库存方法;但是,有足够的特殊情况需要单独实施其中的大多数 .
由于这是教育,看看ndisasm .
结帐 objdump 来源 - 它's a great tool, it contains many opcode tables and it' s源可以为您自己的反汇编程序提供一个很好的基础 .