opcode原理

前缀域

  • 切换操作数大小前缀 : 066h

    • 可以将32位的操作数切换成16位的操作数

B8 00010000 | MOV EAX,0x100     
66:B8 0001 | MOV AX,0x100  

8918       | MOV DWORD PTR DS:[EAX],EBX  
66:8918     | MOV WORD PTR DS:[EAX],BX
  • 切换地址大小(切换寻址模式) : 067h

    • 用于将32位存储器的寻址方式切换成16位的寻址方式(16位的存储器寻址方式中,只能使用bx,si,di,bp寄存器作为内存地址) , 而32位汇编中,可以使用任意寄存器.

66:8918    | MOV WORD PTR DS:[EAX],BX   
67:8918   | MOV DWORD PTR DS:[BX+SI],EBX
  • 重复操作前缀:0f2h,0f3h

F2:A4      | REPNE MOVSB     
F3:A4     | REP MOVSB    
F2:45     | INC EBP   ; 没有起作用  
  • 修改默认段:

3E:8945 00| MOV DWORD PTR DS:[EBP],EAX;3E->ds
26:8918   | MOV DWORD PTR ES:[EAX],EBX;26->es
36:8918   | MOV DWORD PTR SS:[EAX],EBX;36->ss
2E:8918   | MOV DWORD PTR CS:[EAX],EBX;2E->cs
64:8918   | MOV DWORD PTR FS:[EAX],EBX;64->fs
65:8918   | MOV DWORD PTR GS:[EAX],EBX;65->gs

机器码翻译成反汇编的方法

83C404A178812801A35481280168548128018B0D7481280151684881280168448128016840812801FF15A4922801
  1. 查表(intel提供的1字节指令映射表)

    1. 将第一个字节取出, 取查表(例如 83h)

    2. 以高4位作为y轴,以低4位作为x轴, 坐标相交之处,就是这个code域对应的指令了, 如果查找的是group,那么还需要进一步去查group表,(依然使用机器码去查)

      1. 接着需要用83h的下一个字节(C4)作为modR/M域再进一步确认使用group中的哪一个. 将c4展开为二进制11000100

    3. 无论是直接在1字节对照表中,还是在group表中, 得到的都是指令格式: ADD Ev,Ib

      格式解析:

      1. ADD - 指令的助记符

      2. Ev,Ib 说明指令有两个操作数

      3. E - 第一个操作数是寄存器或内存操作数

      4. v - 第一个操作数的大小和当前处理器模式一样(32位时,操作数大小就是32位的)

      5. I - 第二个操作数是一个立即数, 说明在指令的modR/M域后面还有一个Imm域, 保存着指令的立即数操作数(立即数域:04)

      6. b-立即数的大小是一个字节. 说明立即数域的长度是1字节

    4. 目前可以确认指令是: Add Ev,04

    5. Ev中使用的寄存器的名字, 由modR/M域来提供. 需要去查询modR/M

      1. modR/M表的组成:

        1. 表的左列, 是寄存器或内存操作, 在表的顶列,是纯寄存器操作数.

        2. 当操作数的类型是G的时候, 表示操作是纯寄存器. 应当到表的顶列去取出寄存器的名字.

        3. 当操作数的类型是E的时候, 表示操作数可能是寄存器,可能是存储器, 应当在表的左列取出操作数.

        4. 无论在那列, 都有很多寄存器, 此时需要使用操作数的大小来选择一款寄存器.

    6. 当前求出的指令就是: Add esp , 04;

  2. ModR/M域保存着指令的比较复杂的寻址方式。它携带着一下信息

    1. 操作数名称(寄存器、内存地址)

    2. 是否存在SIB域

    3. 是否存在相对偏移

      ModR/M域占一个字节,可以将这一个字节拆分成一下格式。

      89 D8 move eax,eb

      D8=11011000

      Mod Reg R/M

      11 011 000

  3. SIB域主要保存那些寄存器寻址的操作数中,带有乘法运算的部分。

    例如:mov eax,[ebx*4]

13字节汇编指令的赏析

LOCK MOV DWORD PTR ES:[EDX*4+ECX+0AA],11

F0:26:C7 87 91 AA000000 11000000

前缀 OPCODE MODR/M SIB DISPLACEMENT IMMEDIATE

F0:26 C7 84 91 AA000000 11000000

解析例子


;例子1

83C404
A178812801
A354812801
6854812801
8B0D74812801
51684881280168448128016840812801FF15A4922801

code域: A1
mov eax,Ov
O - 存储器直接寻址方式,
说明指令的下一个字节就是一个内存地址
v - 操作数的大小就是`dword ptr`
mov eax,dword ptr[0x01288178]

code域: A3
mov Ov,eax
mov dword ptr[0x1288154],eax

6854812801
code域: 68
push Iz
I - 立即数
z -
push 1288154



8B0D74812801
code域: 8B
Mov Gv,Ev
ModR/M域: 0D
Gv : 在表的顶部: ecx
Ev : 在表的左边: disp32 - 偏移域
偏移域 : 74812801=>0x01288174
mov ecx,[0x1288174]


; 例子2

C7048100100000
C784810010000000100000
898C8100100000

code: C7 => mov Ev,Iz
modR/M: 04
Ev => [--][--]
SIB : 81 左边找到的寄存器 + 顶上找到的寄存器
  然后将找到寄存器作为存储器寻址方式写上
eax*4+ecx
mov [eax*4+ecx] ,01000h

code: C7 => mov Ev,Iz
modR/M: 84
Ev => [--][--]+disp32
SIB : 81 => eax*4+ecx
disp32 : 00100000 => 1000h
[--][--]+disp32 => [ eax*4+ecx+01000h]
Iz : 00100000
最终的指令: mov [eax*4+ecx+01000h],01000h
​ code : 89 => Mov Ev,Gv
modR/M: 8C =>
Ev => [--][--]+disp32
Gv => ecx
SIB : 81 => eax*4+ecx
disp32 => 00100000
最终的指令 :Mov [eax*4+ecx+01000h],ecx


; 例子3

E912563545
E865123314
FF2556781234

code:E9 => jmp Jz
J => 操作是一个偏移值(立即数)
z => 32位
最终的指令:
jmp eip+45355612+5(指令自身长度)

code : E8 => call jz
最终的指令:
call eip+14331265+5

code FF:
modR/M 25 -> 00100101 => jmp Ev
Ev => disp32
disp32 => 56781234 => 034127856h
最终的指令
jmp [034127856h]

汇编4OPCODE的更多相关文章

  1. u-boot源码汇编段简要分析

    Hi,大家好!我是CrazyCatJack,你们可以叫我CCJ或者疯猫.今天我给大家带来的是u-boot的源代码汇编段分析,以后还会给大家讲解后续的C代码,请持续关注哦^_^ 先简单说一下u-boot ...

  2. GCC 预处理、编译、汇编、链接..

    1简介 GCC 的意思也只是 GNU C Compiler 而已.经过了这么多年的发展,GCC 已经不仅仅能支持 C 语言:它现在还支持 Ada 语言.C++ 语言.Java 语言.Objective ...

  3. GDB调试汇编堆栈过程分析

    GDB调试汇编堆栈过程分析 分析过程 这是我的C源文件:click here 使用gcc - g example.c -o example -m32指令在64位的机器上产生32位汇编,然后使用gdb ...

  4. Beennan的内嵌汇编指导(译)Brennan's Guide to Inline Assembly

    注:写在前面,这是一篇翻译文章,本人的英文水平很有限,但内嵌汇编是学习操作系统不可少的知识,本人也常去查看这方面的内容,本文是在做mit的jos实验中的一篇关于内嵌汇编的介绍.关于常用的内嵌汇编(AT ...

  5. 从linux0.11中起动部分代码看汇编调用c语言函数

    上一篇分析了c语言的函数调用栈情况,知道了c语言的函数调用机制后,我们来看一下,linux0.11中起动部分的代码是如何从汇编跳入c语言函数的.在LINUX 0.11中的head.s文件中会看到如下一 ...

  6. C内嵌汇编-格式

    C内嵌汇编-格式: __asm__(汇编语句部分:输出部分:输入部分破坏描述部分);C内嵌汇编以关键字"__asm__"或"asm"开始, 下辖四个部分, 各部 ...

  7. 20145212——GDB调试汇编堆栈过程分析

    GDB调试汇编堆栈过程分析 测试代码 #include <stdio.h> short val = 1; int vv = 2; int g(int xxx) { return xxx + ...

  8. C程序汇编运行模式简析

    SJTUBEAR 原创作品转载请注明出处 /<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 1. 汇编 ...

  9. 生成ARM汇编

    使用ndk即可生成arm汇编 1.首先写好hello.c 2.编写makefile #ndk根目录 NDK_ROOT=E:\Android\android-ndk-r10b #编译器根目录 TOOLC ...

随机推荐

  1. python 高性能web框架 gunicorn+gevent

    参考链接: http://rfyiamcool.blog.51cto.com/1030776/1276364/ http://www.cnblogs.com/nanrou/p/7026789.html ...

  2. spring配置mongodb连接副本集多个节点

    mongodb版本3.4.x 1.配置副本集 先配置副本集,可参考我之前写的文章:http://blog.csdn.net/fuck487/article/details/78287362 注意:必须 ...

  3. C++对象的复制——具有指针成员的类的对象的复制

    //smartvessel@gmail.com class Table{ Name * p; size_t sz; publish: Table(size_t s = 15){p = new Name ...

  4. bzoj3270博物馆——期望概率DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3270 设计一个状态表示两个人分别在两个点的状态,带个标号num[i][j]: 据此得到状态之 ...

  5. node.js适合游戏后台开发吗?

    网站服务器和游戏服务器是怎么样联系到一起的? 百牛信息技术bainiu.ltd整理发布于博客园 1. 游戏分很多种,咱们先来看看MMORPG. 再怎么简单的RPG服务器都免不了处理多人交互的情形,上百 ...

  6. Android Studio 1.5.1

    Android Studio 1.5.1 December 3rd, 2015: For information on what's new in 1.5.1, see the release ann ...

  7. python3练习题四

    循环 题目: 答案: #!/usr/bin/env python3 #-*- coding:utf-8 -*- L = ['Bart', 'Lisa', 'Adam'] for i in L: pri ...

  8. 深度解密Go语言之 map

    目录 什么是 map 为什么要用 map map 的底层如何实现 map 内存模型 创建 map 哈希函数 key 定位过程 map 的两种 get 操作 如何进行扩容 map 的遍历 map 的赋值 ...

  9. Codeforces - 474D - Flowers - 构造 - 简单dp

    https://codeforces.com/problemset/problem/474/D 这道题挺好的,思路是这样. 我们要找一个01串,其中0的段要被划分为若干个连续k的0. 我们设想一个长度 ...

  10. HDU 1230饭前开胃菜

    题意不讲了.. 没思路,上去就是干.... 两个所谓要加的数直接存到数组,开一个标记的数组,然后直接加,乱搞一波,就好了. 细心一点. #include<iostream> #includ ...