结合Intel Manual和libdasm学习汇编指令
参考: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学习汇编指令的更多相关文章
- 学习linux内核时常碰到的汇编指令(1)
转载:http://blog.sina.com.cn/s/blog_4be6adec01007xvg.html 80X86 汇编指令符号大全 +.-.*./∶算术运算符. &∶宏处理操作符. ...
- ARM体系结构和汇编指令
第一节 可编程器件的编程原理 1. 可编程器件的特点 1 . CPU在固定频率的时钟控制下节奏运行 2 . CPU可以通过总线读取外部存储设备中的二进制指令集,然后解码执行 3 . 这些可以被CPU解 ...
- (深入理解计算机系统)AT&T汇编指令
AT&T汇编指令学习(GCC) 寄存器命名原则: 相比inter语法,AT&T语法格式要求所有的寄存器都必须加上取值符"%". 操作码命令格式: 源/目的操作数顺序 ...
- ARM汇编指令调试方法
学习ARM汇编时,少不了对ARM汇编指令的调试.作为支持多语言的调试器,gdb自然是较好的选择.调试器工作时,一般通过修改代码段的内容构造trap软中断指令,实现程序的暂停和程序执行状态的监控.为了在 ...
- ARM汇编指令的一些总结-转
ARM汇编指令的一些总结ARM汇编指令很多,但是真正常用的不是很多,而且需要认真琢磨的又更少了.比较有用的是MOV B BL LDR STR还是通过具体汇编代码来学习吧.@ disable watch ...
- 【嵌入式开发】 ARM 汇编 (指令分类 | 伪指令 | 协处理器访问指令)
作者 : 韩曙亮 博客地址 : http://blog.csdn.net/shulianghan/article/details/42408137 转载请著名出处 本博客相关文档下载 : -- AR ...
- go语言调度器源代码情景分析之五:汇编指令
本文是<go调度器源代码情景分析>系列 第一章 预备知识的第4小节. 汇编语言是每位后端程序员都应该掌握的一门语言,因为学会了汇编语言,不管是对我们调试程序还是研究与理解计算机底层的一些运 ...
- 汇编指令与Intrinsics指令的对应关系汇总
汇编指令与Intrinsics指令的对应关系汇总 参考网址:https://software.intel.com/sites/landingpage/IntrinsicsGuide/ 1.赋值指令:m ...
- 浅析VS2010反汇编 VS 反汇编方法及常用汇编指令介绍 VS2015使用技巧 调试-反汇编 查看C语言代码对应的汇编代码
浅析VS2010反汇编 2015年07月25日 21:53:11 阅读数:4374 第一篇 1. 如何进行反汇编 在调试的环境下,我们可以很方便地通过反汇编窗口查看程序生成的反汇编信息.如下图所示. ...
随机推荐
- MySQL 存储过程-definer和invoker的解释
[definer和invoker的解释] 创建存储过程的时候可以指定 SQL SECURITY属性,设置为 DEFINER 或者INVOKER,用来奉告mysql在执行存储过程的时候,,是以DEFIN ...
- java并发编程笔记(一)——并发编程简介
java并发编程笔记(一)--简介 线程不安全的类示例 public class CountExample1 { // 请求总数 public static int clientTotal = 500 ...
- Struct和Union的sizeof计算
struct 结构体的大小不是简单的成员相加,要考虑存储空间的字节对齐 1.空结构体的大小为1 2.含有static的结构体在计算大小时不算上static变量,因为static存储在全局数据空间,而s ...
- SQL语句的执行顺序和效率
今天上午在开发的过程中,突然遇到一个问题,需要了解SQL语句的执行顺序才能继续,上网上查了一下相关的资料,现整理如下:一.sql语句的执行步骤: 1)语法分析,分析语句的语法是否符合规范,衡量语句中各 ...
- 27-python基础-python3-异常处理(try except)
到目前为止,在 Python 程序中遇到错误,或“异常”,意味着整个程序崩溃.不希望这发生在真实世界的程序中. 相反,希望程序能检测错误,处理它们,然后继续运行. 实例1: 当试图用一个数除以零时 ...
- px2rem-loader(Vue:移动端自适应,px自动转化)
1.下载lib-flexible npm i lib-flexible --save 2.引入lib-flexible import 'lib-flexible/flexible' 3.设置meta标 ...
- 在命令行中插入TAB键
参考man bash: quoted-insert (C-q, C-v) Add the next character typed to the line verbatim. This is how ...
- css页面网址
前端必看的文章 1.CSS设置居中的方案总结 https://juejin.im/post/5a7a9a545188257a892998ef 2.阮一峰老师的网站 http://www.ruanyi ...
- 检查目录下 文件的权限-linux shell脚本
#!/bin/bash #History: #2019/07/23 Fsq #This Program will check Permissions on dir PATH=/bin:/sbin ...
- Arch安装墨刀(产品原型工具)
Arch通过aur安装墨刀的时候报错,查看PKGBUILD发现下载地址错误("https://s3.cn-north-1.amazonaws.com.cn/modao/download&qu ...