zoukankan      html  css  js  c++  java
  • 逆向初级-汇编(一)

    1.1.进制

    进制的定义:
    八进制的定义:由八个符号组成,分别是01234567逢八进一。
    十进制的定义:由十个符号组成,分别是0123456789逢十进一。
    N进制的定义:由N个符号组成,逢N进一。

    1.2、进制的运算

    八进制运算

    2+3=5
    2*3=6
    4+5=11
    4*5=24
    277+333= 632
    276*54= 162
    237-54= 20250
    234/4= 47
    
    #八进制:0 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17 20 21 22 23 24 25 26 27
    

    八进制加法表

    2+3=5
    2*3=6
    4+5=11
    4*5=24
    277+333= 632
    276*54= 162
    237-54= 20250
    234/4= 47
    
    #八进制:0 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17 20 21 22 23 24 25 26 27
    

    八进制加法表
    image
    八进制乘法表
    image

    1.3.二进制简写形式

    计算机为什么使用二进制
    计算机是需要用电的,电路只有两种状态: 1真(通电) 0假(未通电)
    计算机中存储的任何文件、接收的任何指令都是由0和1组成的

    二进制与十六进制

    0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
     0	  1	   2	3	  4   5	   6	7	  8	  9	   A	 B	  C	   D   E    F
    

    1.4.数据宽度

    数据宽度
    数学上的数字,是没有大小限制的,可以无限的大。但在计算机中,由于受硬件的制约,数据都是有长度限制的(我们称为数据宽度),超过最大宽度的数据会被丢弃。

    计算机中常见的数据宽度:

    1)位(BIT) 1位
    2)字节(Byte) 8位
    3)字(Word) 16位
    4)双字(Doubleword) 32位

    存储范围:
    字节(Byte): 0 ~ 0xFF
    字(Word): 0 ~ 0xFFFF
    双字:0~ 0xFFFFFFFF
    如果要存储的数据超过最大宽度,那么多余的数据将被丢弃!

    1.5.无符号数有符号数

    无符号数的编码规则

    10011010
    十六进制:0x9A
    十进制:154
    

    有符号数的编码规则

    正数编码规则(第一位是0),如果是正数就和无符号数编码规则一样
    00011010
    
    负数编码规则(第一位是1)
    10011010
    

    1.6.原码反码补码

    有符号数的编码规则
    原码:最高位为符号位,其余各位为数值本身的绝对值
    反码:
    正数:反码与原码相同
    负数:符号位为1,其余位对原码取反
    补码:
    正数:补码与原码相同
    负数:符号位为1,其余位对原码取反加1

    -1
    原码:10000001
    反码:11111110
    补码:11111111     (负数在计算机里面是采用补码的形势存储的)
    
    -7
    原码:10000111
    反码:11111000
    补码:11111001     (负数在计算机里面是采用补码的形势存储的)
    

    1.7.计算机不会做加法

    image
    image
    image
    image
    image
    image

    1.8.位运算之加减乘除

    4+5=的运算过程
    image
    4-5=?的运算过程
    image

    1.9.汇编环境安装

    下载DTdebug工具,打开后设置UDD和plugin的路劲。Options-->Appearance
    image
    image

    1.10.通用寄存器

    1寄存器
    存储数据:
    CPU>内存>硬盘
    32位CPU: 8 16 32
    64位CPU: 8 16 32 64

    2、通用寄存器
    32位通用寄存器:
    EAX
    ESP
    ECX
    EBP
    EDX
    ESI
    EBX
    EDI

    3、MOV指令
    <1> 立即数到内存
    <2>寄存器到内存
    <3>内存到寄存器

    按F8单步运行
    image
    4.通用寄存器
    image

    1.11.内存

    image
    2、内存地址
    <1>内存太大没法起名字,所以只能用编号。当我们想向内存中存储数据,或者从内存中读取数据时,必须用到这个编号,就像写信必须要写收信人地址一样。
    <2>这个编号又称为内存地址(32位,前面0可以省略)。

    3、往内存中写入值

    MOV DWORD PTR DS:[19FF90],12345678
    
    # DWORD表示四个字节长度
    #PTR DS:[19FF90]表示内存地址
    

    1.12.内存地址的五种形式

    1、形式一: [立即数]
    读取内存的值:
    MOV EAX,DWORD PTR DS:[Ox13FFC4]
    向内存中写入数据:
    MOV DWORD PTR DS:[0x13FFC4],EAX

    2、形式二: [reg] reg代表寄存器可以是8个通用寄存器中的任意一个
    读取内存的值:
    MOV ECX,0x13FFD0
    MOV EAX,DWORD PTR DS:[ECX]
    向内存中写入数据:
    MOV EDX,0x13FFD8
    MOV DWORD PTR DS:[EDX],0x87654321

    3、形式三: [reg+立即数]
    读取内存的值:
    MOV ECX,0x1 3FFD0
    MOV EAX,DWORD PTR DS:[ECX+4]
    向内存中写入数据:
    MOV EDX,0x13FFD8
    MOV DWORD PTR DS:[EDX+0xC],0x87654321

    4、形式四: [reg+reg*{1,2,4,8}]
    读取内存的值:
    MOV EAX,13FFC4
    MOV ECX,2
    MOV EDX,DWORD PTR DS:[EAX+ECX4]
    向内存中写入数据:
    MOV EAX,13FFC4
    MOV ECX,2
    MOV DWORD PTR DS:[EAX+ECX
    4],87654321

    5、形式五: [reg+reg*{1 ,2,4,8}+立即数]
    读取内存的值:
    MOV EAX,13FFC4
    MOV ECX,2
    MOV EDX,DWORD PTR DS:[EAX+ECX4+4]
    向内存中写入数据:
    MOV EAX,13FFC4
    MOV ECX,2
    MOV DWORD PTR DS:[EAX+ECX
    4+4],87654321

    1.13.存储模式

    image
    2、DTDEBUG内存窗口的使用
    <1>分别以字节/字/双字形式来查看内存(db dw dd)
    image
    <2>向内存中写入四个字节的数据,并观察存储形式(大端存储/小端存储)
    image

    1.14.常用汇编指令

    1、MOV指令
    指令格式:
    1、MOV r/m8,r8 r通用寄存器
    2、MOV r/m16,r16 m代表内存
    3、MOV r/m32,r32 ; imm代表立即数
    4、MOVr8,r/m8 r8代表8位通用寄存器
    5、MOV r16,r/m16 m8代表8位内存
    6、MOV r32,r/m32 ; imm8代表8位立即数
    7、MOV r8, imm8
    8、MOV r16, imm16
    9、MOV r32, imm32

    2、ADD指令
    指令格式:
    ADD r/m8, imm8
    ADD r/m16, imm16
    ADD r/m32,imm32
    ADD r/m16, imm8
    ADD r/m32, imm8
    ADD r/m8, r8
    ADD r/m16, r16
    ADD r/m32, r32
    ADD r8, r/m8
    ADD r16, r/m16
    ADD r32, r/m32

    3、SUB指令
    指令格式:
    SUB r/m8, imm8
    SUB r/m1 6,imm16
    SUB r/m32,imm32
    SUB r/m16, imm8
    SUB r/m32, imm8
    SUB r/m8, r8
    SUB r/m16, r16
    SUB r/m32, r32
    SUB r8, r/m8
    SUB r16, r/m16
    SUB r32, r/m32

    4、AND指令
    AND r/m8, imm8
    AND r/m16,imm16
    AND r/m32,imm32
    AND r/m16, imm8
    AND r/m32, imm8
    AND r/m8, r8
    AND r/m16, r16
    AND r/m32, r32
    AND r8, r/m8
    AND r16, r/m16
    AND r32, r/m32

    5、OR指令
    OR r/m8, imm8
    OR r/m16 ,imm16
    OR r/m32,imm32
    OR r/m16, imm8
    OR r/m32, imm8
    OR r/m8, r8
    OR r/m16, r16
    OR r/m32, r32
    OR r8, r/m8
    OR r16, r/m16
    OR r32, r/m32

    6、XOR指令
    XOR r/m8, imm8
    XOR r/m16,imm16
    XOR r/m32 ,imm32
    XOR r/m16, imm8
    XOR r/m32, imm8
    XOR r/m8, r8
    XOR r/m16, r16
    XOR r/m32, r32
    XOR r8, r/m8
    XOR r16, r/m16
    XOR r32, r/m32

    7、NOT指令
    NOT r/m8
    NOT r/m16
    NOT r/m32

    1.15.内存复制指令

    1、MOVS指令:移动数据内存-内存
    BYTENWORD/DWORD
    MOVS BYTE PTR ES:[EDJ,BYTE PTR DS:[ESI] 简写为: MOVSB
    MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI] 简写为: MOVSW
    MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] 简写为: MOVSD

    例子: .
    MOV EDI,12FFD8
    MOV ESI,12FFD0
    MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
    观察EDI的值
    修改标志寄存器中D位的值,然后在执行下面的指令:
    MOV EDI,12FFD8
    MOV ESI,12FFD0MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]

    2、STOS指令: 将AI/AX/EAX的值存储到[EDI]指定的内存单元
    STOS BYTE PTR ES:[EDI] 简写为STOSB
    STOS WORD PTR ES:[EDI] 简写为STOSW
    STOS DWORD PTR ES:[EDI] 简写为STOSD

    例子:

    MOV EAX, 12345678 观察EDI的值
    MOV EDI, 12FFC4
    STOS BYTE PTR ES:[EDI]
    STOS WORD PTR ES:[EDI]
    STOS DWORD PTR ES:[EDI]
    修改标志寄存器中D位的值,然后在执行下面的指令:
    MOV EAX, 12345678 观察EDI的值
    MOV EDI, 12FFC4
    STOS BYTE PTR ES:[EDI]
    STOS WORD PTR ES:[EDI]
    STOS DWORD PTR ES:[EDI]

    3、REP指令: 按计数寄存器(ECX)中指定的次数重复执行字符串指令
    MOV ECX,10
    REP MOVSD
    REP STOSD

    1.16.堆栈相关指令

    1、什么是堆栈?
    1)就是一块内存,操作系统在程序启动的时候已经分配好的,供程序执行时使用。
    2)和数据结构的堆栈无关。
    3)查看堆栈。

    2、栈指针寄存器
    ESP中存储了当前的堆栈用到哪里了

    3、堆栈的使用
    <1>存储数据
    <2>修改栈顶指针

    4、PUSH指令
    <1>向堆栈中压人数据
    <2>修改栈项指针ESP寄存器
    指令格式:
    1、PUSH r32
    2、PUSH r16
    3、PUSH m16
    4、PUSH m32
    5、PUSH imm8/imm1 6/imm32

    5、POP指令:
    <1>将栈顶数据存储到寄存器/内存
    <2>修改栈项指针ESP寄存器
    指令格式:|
    1、POP r32
    2、POPr16
    3、POP m16
    4、POP m32

    1.17.修改EIP的指令

    1、JMP指令:
    MOV EIP,寄存器/立即数/内存 简写为 JMP寄存器/立即数/内存

    2、CALL指令:
    PUSH下一行地址
    MOV EIP,立即数/寄存器/内存 简写为: CALL立即数/寄存器/内存
    与JMP唯--的区别:
    在堆栈中存储Call指令下一-行地址

    3、RET指令:
    ADD ESP,4
    MOV EIP,[ESP-4]

    简写为: RET

    1.18.汇编眼中的函数

    1、什么是函数
    函数就是一系列指令的集合,为了完成某个会重复使用的特定功能。
    例子:向寄存器中赋值

    2、如何执行一个函数?即函数调用
    <1>用JMP来执行函数
    <2> 用CALL来执行函数

    3、 什么是参数?什么是返回值?
    例子:编写一个函数,能够得到任意2个整数的值。

    1.19.堆栈平衡

    什么是堆栈平衡?
    1)如果要返回父程序,则当我们在堆栈中进行堆栈的操作的时候,一定要保证在RET这条指令之前,ESP指向的是我们压入栈中的地址。
    2)如果通过堆栈传递参数了,那么在函数执行完毕后,要平衡参数导致的堆栈变化。

    1.20.JCC指令

    1、JE, JZ 结果为零则跳转(相等时跳转) ZF=1
    2、JNE, JNZ 结果不为零则跳转(不相等时跳转) ZF=0
    3、JS 结果为负则跳转 SF=1
    4、JNS 结果为非负则跳转 SF=0
    5、JP, JPE 结果中1的个数为偶数则跳转 PF=1
    6、JNP, JPO 结果中1的个数为偶数则跳转 PF=0
    7、J0 结果溢出了则跳转 0F=1
    8、JNO 结果没有溢出则跳转 0F=0

    9、JB, JNAE 小于则跳转(无符号数) CF=1
    10、JNB, JAE 大于等于则跳转(无符号数) CF=0
    11、JBE, JNA 小于等于则跳转(无符号数) CF=1 or ZF=1
    12、JNBE, JA 太于则跣转(无符号数) CF=0 and ZF=0中
    13、JL, JNGE 小于则跳转(有符号数) SF≠OF

    14、JN, JGE 大于等于则跳转(有符号数) SF=OF
    15、JLE, JNG 小于等于则跳转(有符号数) ZF=1 or SF≠0F
    16、JNLE, JG 因于则来转(有符号数) ZF=0 and SF=OF

    1、标志寄存器:EFLAGS
    image
    2、CF (bit 0) [Carry fiag]
    若算术操作产生的结果在最高有效位(most-significant bit)发生进位或借位则将其置1,反之清零。
    这个标志通常用来指示无符号整型运算的溢出状态。

    例:
    MOV AL,0xFE MOV AL,0x7F
    ADD AL,2 或者 SUB AL ,0xFF

    3、PF(bit 2) [Parity flag]
    如果结果的最低有效字节(least-significant byte)包含偶数个1位则该位置1,否则清零。

    利用PF可进行奇偶校验检查:
    需要传输"11001110",数据中含5个"1", 所以其奇校验位为"0",同时把"110011100"传输给接收方,接收方收到数据后再- - 次计算奇偶性,"110011100"中仍然含有5个"1",所以接收方计算出的奇校验位还是"0",与发送方一致,表示在此次传输过程中未发生错误

    例子:
    MOV AL,OCE
    ADDAL,0

    4、AF(bit 4) [Adjust Flag]
    如果算术操作在结果的第3位发生进位或借位则将该标志置1,否则清零。
    这个标志在BCD(binary-code decimal)算术运算中被使用。

    5、ZF(bit 6) [Zero flag]
    若结果为0则将其置1,反之清零。
    经常与CMP或者TEST等指令-起使用:

    例1:判断2个值是否相等

    MOV EAX, 100
    MOV ECX, 100
    CMP EAX, ECX
    (CMP指令相当干SUB指令.但是相减的结果并不保存到第一个操作数中)

    例2:判断某个值是否为0
    TEST EAX,EAX
    (TEST指令相当于AND指令,但是与的结果并不保存到第-一个操作数中)

    6、SF(bit 7) [Sign flag]
    该标志被设置为有符号整型的最高有效位。
    (0指示结果为正,反之则为负)
    例子:
    MOV AL ,0x7F MOV AL ,0xFE
    ADD AL,2 ADDAL,2

    7、OF(bit 11) [Overflow flag]
    溢出标志OF用于反映有符号数加减运算所得结果是否溢出。

    可以这样理解:
    如果是无符号数运算,是否溢出看CF位。
    如果是有符号数运算,是否溢出看OF位。
    例子:
    MOV AL ,0x7F
    ADD AL,2

    8、DF(bit 10) [Direction Flag]
    这个方向标志控制串指令(MOVS, CMPS, SCAS, LODS以及STOS)。设置DF
    标志使得串指令自动递减(从高地址向低地址方向处理字符串),清除该标志则使
    得串指令自动递增。
    STD以及CLD指令分别用于设置以及清除DF标志。

    作者:zhang_derek

    个性签名:其实人跟树一样,越是向往高处的阳光,它的根就越要伸向黑暗的地底。

  • 相关阅读:
    python之socket编程
    python之异常处理
    面向对象进阶
    openstack的网络配置
    VLAN,GRE,VXLAN
    三节点搭建openstack-Mitaka版本
    矩阵转换
    判断区域相交的方法
    Centos 6.5 Multipath 初始配置
    CentOS开机自动运行程序的脚本
  • 原文地址:https://www.cnblogs.com/derek1184405959/p/14635484.html
Copyright © 2011-2022 走看看