参考:http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html

https://code.google.com/p/libdasm/

http://nathanmarz.com/blog/you-should-blog-even-if-you-have-no-readers.html(共勉)

汇编指令的格式如下图所示:

参考:http://www.mouseos.com/x64/doc6.html

1. get_instruction

get_instruction函数是libdasm的核心,先看一下该函数的注释和原型

// Fetch instruction

 

/*

 * The operation is quite straightforward:

 *

 * - determine actual opcode (skip prefixes etc.)

 * - figure out which instruction table to use

 * - index the table with opcode

 * - parse operands

 * - fill instruction structure

 *

 * Only point where this gets hairy is those *brilliant*

 * opcode extensions....

 *

 */

int get_instruction(PINSTRUCTION inst, BYTE *addr, enum Mode mode) {

该函数分为以下几个部分:

1.1 略过prefix, 获取到实际的opcode

get_real_instruction来做这个工作。

对于单字节opcode,该函数什么也不做;

对于2字节opcode

// 2-byte opcode

        case 0x0f:

            *index += 1;

            *flags |= EXT_T2;

            break;

跳过0x0F前缀;

对于强制前缀的opcode,(Mandatory Prefix)

// Prefix group 2

        case 0x2e:

            *index += 1;

            // Clear previous flags from same group (undefined effect)

            *flags &= 0xff00ffff;

            *flags |= PREFIX_CS_OVERRIDE;

            get_real_instruction(addr + 1, index, flags);

            break;

        case 0x36:

            *index += 1;

            *flags &= 0xff00ffff;

            *flags |= PREFIX_SS_OVERRIDE;

            get_real_instruction(addr + 1, index, flags);

            break;

        case 0x3e:

            *index += 1;

            *flags &= 0xff00ffff;

            *flags |= PREFIX_DS_OVERRIDE;

            get_real_instruction(addr + 1, index, flags);

            break;

        case 0x26:

            *index += 1;

            *flags &= 0xff00ffff;

            *flags |= PREFIX_ES_OVERRIDE;

            get_real_instruction(addr + 1, index, flags);

            break;

        case 0x64:

            *index += 1;

            *flags &= 0xff00ffff;

            *flags |= PREFIX_FS_OVERRIDE;

            get_real_instruction(addr + 1, index, flags);

            break;

        case 0x65:

            *index += 1;

            *flags &= 0xff00ffff;

            *flags |= PREFIX_GS_OVERRIDE;

            get_real_instruction(addr + 1, index, flags);

            break;

        // Prefix group 3 or 3-byte opcode

        case 0x66:

            // Do not clear flags from the same group!!!!

            *index += 1;

            *flags |= PREFIX_OPERAND_SIZE_OVERRIDE;

            get_real_instruction(addr + 1, index, flags); 

            break;

        // Prefix group 4

        case 0x67:

            // Do not clear flags from the same group!!!!

            *index += 1;

            *flags |=  PREFIX_ADDR_SIZE_OVERRIDE;

            get_real_instruction(addr + 1, index, flags); 

            break;

设置相应的flag,然后从下一个字节取真正的opcode;

常见的前缀如下表所示:

1.2 确定使用哪张映射表

在opcode_tables.h中定义了几张不同和映射表

// 1-byte opcodes

INST inst_table1[256] = {

// 2-byte instructions

INST inst_table2[256] = {

// 3-byte instructions, prefix 0x66

 

// Yeah, I know, it's waste to use a full 256-instruction table but now

// I'm prepared for future Intel extensions ;-)

 

INST inst_table3_66[256] = {

// 3-byte instructions, prefix 0xf2

 

INST inst_table3_f2[256] = {

// 3-byte instructions, prefix 0xf3

 

INST inst_table3_f3[256] = {

映射表中条目的内容是对于INST结构体的描述

// struct INST is used internally by the library

typedef struct _INST {

    DWORD type;        // InstructionType type and flags

    const char *mnemonic;    // InstructionType mnemonic

    int flags1;        // First operand flags (if any)

    int flags2;        // Second operand flags (if any)

    int flags3;        // Additional operand flags (if any)

    int modrm;        // Is MODRM byte present?

    short eflags_affected;    // Processor eflags affected

    short eflags_used;      // Processor eflags used by this instruction

    int iop_written;    // mask of affected implied registers (written)

    int iop_read;        // mask of affected implied registers (read)

} INST, *PINST;

举一例:

{ INSTRUCTION_TYPE_ADD,    "add",       AM_E|OT_b|P_w,               AM_G|OT_b|P_r,             FLAGS_NONE,   1, EFL_MATH, 0, 0, 0 },

比较重要的字段是3-5,分别代表着参数的类型

AM_[X]代表Addressing Method,即寻址方法,通过什么方法找到参数

// Operand Addressing Methods, from the Intel manual

#define MASK_AM(x) ((x) & 0x00ff0000)

#define AM_A 0x00010000        // Direct address with segment prefix

#define AM_C 0x00020000        // MODRM reg field defines control register

#define AM_D 0x00030000        // MODRM reg field defines debug register

#define AM_E 0x00040000        // MODRM byte defines reg/memory address

#define AM_G 0x00050000        // MODRM byte defines general-purpose reg

#define AM_I 0x00060000        // Immediate data follows

#define AM_J 0x00070000        // Immediate value is relative to EIP

#define AM_M 0x00080000        // MODRM mod field can refer only to memory

#define AM_O 0x00090000        // Displacement follows (without modrm/sib)

#define AM_P 0x000a0000        // MODRM reg field defines MMX register

#define AM_Q 0x000b0000        // MODRM defines MMX register or memory 

#define AM_R 0x000c0000        // MODRM mod field can only refer to register

#define AM_S 0x000d0000        // MODRM reg field defines segment register

#define AM_T 0x000e0000        // MODRM reg field defines test register

#define AM_V 0x000f0000        // MODRM reg field defines XMM register

#define AM_W 0x00100000        // MODRM defines XMM register or memory 

// Extra addressing modes used in this implementation

#define AM_I1  0x00200000    // Immediate byte 1 encoded in instruction

#define AM_REG 0x00210000    // Register encoded in instruction

#define AM_IND 0x00220000    // Register indirect encoded in instruction

OT_[X]代表参数的类型Operand Type,即参数的长度

// Operand Types, from the intel manual

#define MASK_OT(x) ((x) & 0xff000000)

#define OT_a  0x01000000

#define OT_b  0x02000000    // always 1 byte

#define OT_c  0x03000000    // byte or word, depending on operand

#define OT_d  0x04000000    // double-word

#define OT_q  0x05000000    // quad-word

#define OT_dq 0x06000000    // double quad-word

#define OT_v  0x07000000    // word or double-word, depending on operand

#define OT_w  0x08000000    // always word

#define OT_p  0x09000000    // 32-bit or 48-bit pointer

#define OT_pi 0x0a000000    // quadword MMX register

#define OT_pd 0x0b000000    // 128-bit double-precision float

#define OT_ps 0x0c000000    // 128-bit single-precision float

#define OT_s  0x0d000000    // 6-byte pseudo descriptor

#define OT_sd 0x0e000000    // Scalar of 128-bit double-precision float

#define OT_ss 0x0f000000    // Scalar of 128-bit single-precision float

#define OT_si 0x10000000    // Doubleword integer register

#define OT_t  0x11000000    // 80-bit packed FP data

P_[X]代表参数的Permission,即参数允许的操作,也就是该条指令会对参数做什么样的操作(r, w, x)

// Operand permissions

#define MASK_PERMS(x) ((x) & 0x0000f000)

#define P_r   0x00004000    // Read

#define P_w   0x00002000    // Write

#define P_x   0x00001000    // Execute

1.3 映射

1.4 解析operand

Operand有三种类型:

// Operand types

enum Operand {

    OPERAND_TYPE_NONE,    // operand not present

    OPERAND_TYPE_MEMORY,    // memory operand ([eax], [0], etc.)

    OPERAND_TYPE_REGISTER,    // register operand (eax, mm0, etc.)

    OPERAND_TYPE_IMMEDIATE,    // immediate operand (0x1234)

};

其中,immediate是直接地址,也可以称为静态地址,即在指令中明确给出的地址;

而register和memory都是间接地址,可以称为动态地址,只有在程序真正运行时才能确定的地址。

即使是静态解析程序,我们也可以对于给定的内存地址,寄存器,逐条指令地模拟其内容的变化,这就是模拟器的原理,说白了,模拟器终归还属于静态解析,而算不上是真正的动态。

1.5 填充结构体

结合Intel Manual和libdasm学习汇编指令的更多相关文章

  1. 学习linux内核时常碰到的汇编指令(1)

     转载:http://blog.sina.com.cn/s/blog_4be6adec01007xvg.html 80X86 汇编指令符号大全 +.-.*./∶算术运算符. &∶宏处理操作符. ...

  2. ARM体系结构和汇编指令

    第一节 可编程器件的编程原理 1. 可编程器件的特点 1 . CPU在固定频率的时钟控制下节奏运行 2 . CPU可以通过总线读取外部存储设备中的二进制指令集,然后解码执行 3 . 这些可以被CPU解 ...

  3. (深入理解计算机系统)AT&T汇编指令

    AT&T汇编指令学习(GCC) 寄存器命名原则: 相比inter语法,AT&T语法格式要求所有的寄存器都必须加上取值符"%". 操作码命令格式: 源/目的操作数顺序 ...

  4. ARM汇编指令调试方法

    学习ARM汇编时,少不了对ARM汇编指令的调试.作为支持多语言的调试器,gdb自然是较好的选择.调试器工作时,一般通过修改代码段的内容构造trap软中断指令,实现程序的暂停和程序执行状态的监控.为了在 ...

  5. ARM汇编指令的一些总结-转

    ARM汇编指令的一些总结ARM汇编指令很多,但是真正常用的不是很多,而且需要认真琢磨的又更少了.比较有用的是MOV B BL LDR STR还是通过具体汇编代码来学习吧.@ disable watch ...

  6. 【嵌入式开发】 ARM 汇编 (指令分类 | 伪指令 | 协处理器访问指令)

    作者 : 韩曙亮 博客地址 : http://blog.csdn.net/shulianghan/article/details/42408137 转载请著名出处 本博客相关文档下载 :  -- AR ...

  7. go语言调度器源代码情景分析之五:汇编指令

    本文是<go调度器源代码情景分析>系列 第一章 预备知识的第4小节. 汇编语言是每位后端程序员都应该掌握的一门语言,因为学会了汇编语言,不管是对我们调试程序还是研究与理解计算机底层的一些运 ...

  8. 汇编指令与Intrinsics指令的对应关系汇总

    汇编指令与Intrinsics指令的对应关系汇总 参考网址:https://software.intel.com/sites/landingpage/IntrinsicsGuide/ 1.赋值指令:m ...

  9. 浅析VS2010反汇编 VS 反汇编方法及常用汇编指令介绍 VS2015使用技巧 调试-反汇编 查看C语言代码对应的汇编代码

    浅析VS2010反汇编 2015年07月25日 21:53:11 阅读数:4374 第一篇 1. 如何进行反汇编 在调试的环境下,我们可以很方便地通过反汇编窗口查看程序生成的反汇编信息.如下图所示. ...

随机推荐

  1. SCI小论文投稿记录

    英文小论文投的是SCI 3区的一个刊物,收录在spring,ei等, 投稿的时候2019/2/3影响因子2.8左右 现在2019/8/13  影响因子3.844 先科普下论文的各个状态 1. Subm ...

  2. Opengl ES Glew库 ----- By YDD的铁皮锅

    前一篇随笔我写了Opengl的窗口创建,这一篇随笔我要写OpenGL glew库的使用.首先需要引入头文件h,库文件Lib和动态链接库DLL, 百度搜索OpenGL glew库找到这个纯英文网站,尽量 ...

  3. python学习笔记:python简介和入门

    编程语言各有千秋.C语言适合开发那些追求运行速度.充分发挥硬件性能的程序.而Python是用来编写应用程序的高级编程语言. Python就为我们提供了非常完善的基础代码库,覆盖了网络.文件.GUI.数 ...

  4. Python37不能启动pyspider

    报错内容: Traceback (most recent call last): File "/usr/local/var/pyenv/versions/3.7.3/bin/pyspider ...

  5. css页面网址

    前端必看的文章 1.CSS设置居中的方案总结  https://juejin.im/post/5a7a9a545188257a892998ef 2.阮一峰老师的网站 http://www.ruanyi ...

  6. 一、基础项目构建,引入web模块,完成一个简单的RESTful API

    一.Spring Boot的主要优点: 为所有Spring开发者更快的入门 开箱即用,提供各种默认配置来简化项目配置 内嵌式容器简化Web项目 没有冗余代码生成和XML配置的要求 二.使用maven构 ...

  7. 学习记录:@Transactional 事务不生效

    测试时使用spring boot2.2.0,在主类中调用,@Transactional 不起作用,原代码如下: @SpringBootApplication @Slf4j @Component pub ...

  8. 【Luogu】【关卡2-2】交叉模拟(2017年10月)

    任务说明:这里也是模拟,但是会混有些别的部分.思维难度不大,但是编写起来会有些难度.

  9. Java优化性能

    尽量在合适的场合使用单例使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面:第一,控制资源的使用,通过线程同步来控制资源的并 ...

  10. 多线程的设计模式:Future、Master-Worker

    一 简介 并行设计模式属于设计优化的一部分,它是对一些常用的多线程结构的总结和抽象.与串行程序相比,并行程序的结构通常更为复杂,因此合理的使用并行模式在多线程开发中更具有意义,在这里主要介绍==Fut ...