参考: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. sed 对文件进行操作

    首先我们想不进入一个文件 对文件进行操作 那么久需要用到sed了 在某个变量之前添加内容: sed -i 's/原内容/要添加内容/g' 文件名 sed -i 's/原内容/要添加内容&/' ...

  2. interleave two text files with specified lines

    a_file=$1 a_step=$2 b_file=$3 b_step=$4 a_start=1 let a_end=$a_start+$a_step b_start=1 let b_end=$b_ ...

  3. (转)Adaboost

    基本原理 Adaboost算法基本原理就是将多个弱分类器(弱分类器一般选用单层决策树)进行合理的结合,使其成为一个强分类器. Adaboost采用迭代的思想,每次迭代只训练一个弱分类器,训练好的弱分类 ...

  4. 点读系列《jmeter官方用户手册》

    官网:http://jmeter.apache.org/usermanual/ 说明:十八元件.十九属性.二十函数,涉及清单内容暂未仔细阅读,个人觉得一是仅供使用参考,二是适合单独写文章来解读 一.让 ...

  5. Apache和Tomcat的区别是什么?

    Apache 和 Tomcat 都是web网络服务器,两者既有联系又有区别,在进行HTML.PHP.JSP.Perl等开发过程中,需要准确掌握其各自特点,选择最佳的服务器配置. Apache是web服 ...

  6. 安装node --- 与升级

    1.安装node流程,请参照菜鸟教程的安装教程   http://www.runoob.com/nodejs/nodejs-install-setup.html 2.这里说一下踩的坑, 问题一.Win ...

  7. sql语句(删除重复数据只保留一条)

    用SQL语句,删除掉重复项只保留一条 在几千条记录里,存在着些相同的记录,如何能用SQL语句,删除掉重复的呢 1.查找表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断 select ...

  8. Hibernate4教程六(2):基本实现原理

    整体流程 1:通过configuration来读cfg.xml文件 2:得到SessionFactory 工厂 3:通过SessionFactory 工厂来创建Session实例 4:通过Sessio ...

  9. docker部署一个简单的mian.py项目文件

    安装docker yum install -y docker  启动docker systemctl start docker   查询可安装的Python版本,默认centos python 2.7 ...

  10. 2018-8-29-Roslyn-静态分析

    title author date CreateTime categories Roslyn 静态分析 lindexi 2018-08-29 09:10:19 +0800 2018-03-13 14: ...