逆向-汇编

本文详细介绍了x86架构中通用寄存器的结构和使用,包括EAX、CX、DX等,并讲解了基本的运算指令如ADD、SBB、XCHG,以及数据移动指令MOV、STOS和寻址模式。此外,还涵盖了流程控制指令如JCC、CALL、RET,以及如何处理堆栈中的数据。最后,讨论了标志寄存器,如CF、PF、ZF、SF和OF的作用及其在不同运算中的影响。
摘要由CSDN通过智能技术生成

通用寄存器

寄存器编号(二进制)编号(十进制)
32位16位8位
EAXAXAL0000
ECXCXCL0011
EDXDXDL0102
EBXBXBL0113
ESPSPAH1004
EBPBPCH1015
ESISIDH1106
EDIDIBH1117

寄存器结构

(AX在EAX中,AH和AL在AX中)

31 1615 87 0
EAXAX(AH)AL
ECXCX(CH)CL
EDXDX(DH)DL
EBXBX(BH)BL
ESPSP
EBPBP
ESISI
EDIDI

运算指令

ADD

两边不能同时为内存

ADC:带进位加法

两边不能同时为内存,宽度要一样

C:carry带

ADC AL,CL --------AL=AL+CL+CF

ADC BYTE PTR DS:[12FFC4],2

ADC BYTE PTR DS:[12FFC4],AL

SBB:带借位减法

两边不能同时为内存,宽度要一样

B:borrow借

SBB AL,CL --------AL=AL-CL-CF

SBB BYTE PTR DS:[12FFC4],2

SBB BYTE PTR DS:[12FFC4],AL

XCHG:交换数据

两边不能同时为内存,宽度要一样

XCHG AL,CL

XCHG BYTE PTR DS:[12FFC4],EAX

XCHG BYTE PTR DS:[12FFC4],AL

MOVS:移动数据

内存-内存

MOVS BYTE PTR ES:[EDI],BYTE PTR ES:[ESI] 简写为MOVSB

在ESI存的地址里面取出一个字节给内存编号为EDI值的地方

移动后:若DF=0 ESI+=1 EDI+=1 若DF=1 ESI-=1 EDI-=1

MOVS WORD PTR ES:[EDI],WORD PTR ES:[ESI] 简写为MOVSW

移动后:若DF=0 ESI+=2 EDI+=2 若DF=1 ESI-=2 EDI-=2

MOVS DWORD PTR ES:[EDI],DWORD PTR ES:[ESI] 简写为MOVSD

移动后:若DF=0 ESI+=4 EDI+=4 若DF=1 ESI-=4 EDI-=4

STOS指令

将AL/AX/EAX/的值储存到[EDI]指定的内存单元

STOS BYTE PTR ES:[EDI] 简写为STOSB

移动后:若DF=0 EDI-=1 若DF=1 EDI+=1

STOS WORD PTR ES:[EDI] 简写为STOSW

移动后:若DF=0 EDI-=2 若DF=1 EDI+=2

STOS DWORD PTR ES:[EDI] 简写为STOSD

移动后:若DF=0 EDI-=4 若DF=1 EDI+=4

REP指令

按计数寄存器(ECX)中指定的次数重复执行字符串指令

MOV ECX,10

REP MOVSD 重复16次movsd操作

REP STOSD

JCC

JMP

唯一作用是无条件修改EIP的值,没有对栈和寄存器产生影响。

JMP 寄存器/立即数
本质是MOV EIP,寄存器/立即数,EIP只能由JMP指令修改

CALL

PUSH 地址B

MOV EIP,地址A/寄存器 简写为:CALL 地址A/寄存器

第一个作用和JMP一样,MOV EIP,寄存器/立即数。
第二个作用,把CALL指令的写一个指令地址push到栈顶(修改ESP)
CALL指令还没执行,怎么知道下一行指令的地址?
根据CALL指令占用的数据宽度,加偏移量去算,比如CALL这条指令,地址0X004183D7中数据为E8 21 00 00 00,有5个字节,下一行指令的地址就是地址偏移5

RET指令

本质是POP EIP
RET指令通常和CALL成对出现,把CALL压栈的地址POP EIP,让程序回归原来的流程

LEA ESP,[ESP+4]

MOV EIP,[ESP-4] 简写为:RET

CMP指令

指令格式:CMP R/M,R/M/IMM 两边不能同时为内存

该指令是比较两个操作数,实际上,它相当于SUB指令,但是相减的结构并不保存到第一个操作数中。只是根据相减的结果来改变零标志位的。当两个操作数相等的时候,零标志位置1

TEST 指令

指令格式:TEST R/M,R/M/IMM 两边不能同时为内存

该指令在一定程序上和CMP指令时类似,两个数值进行与操作,结果不保存,但是会改变相应标志位

与操作:1 and 1 =1;1 and 0 = 0; 0 and 1 = 0; 0 and 0 = 0

常见用法:用这个指令可以确定某个寄存器是否等于0

TEST EAX,EAX 观察Z位

其他

JCC指令只看标志寄存器

所有JCC指令的动作->根据标志寄存器修改EIP的值

JCC指令中文含义英文原意检查符号位典型C应用
JZ/JE若为0则跳转;若相等则跳转jump if zero;jump if equalZF=1if (i == j);if (i == 0);
JNZ/JNE若不为0则跳转;若不相等则跳转jump if not zero;jump if not equalZF=0if (i != j);if (i != 0);
JS若为负则跳转jump if signSF=1if (i < 0);
JNS若为正则跳转jump if not signSF=0if (i > 0);
JP/JPE若1出现次数为偶数则跳转jump if Parity (Even)PF=1
JNP/JPO若1出现次数为奇数则跳转jump if not parity (odd)PF=0
JO若溢出则跳转jump if overflowOF=1
JNO若无溢出则跳转jump if not overflowOF=0
JC/JB/JNAE若进位则跳转;若低于则跳转;若不高于等于则跳转jump if carry;jump if below;jump if not above equalCF=1if (i < j);
JNC/JNB/JAE若无进位则跳转;若不低于则跳转;若高于等于则跳转jump if not carry;jump if not below;jump if above equalCF=0if (i >= j);
JBE/JNA若低于等于则跳转;若不高于则跳转jump if below equal;jump if not aboveZF=1或CF=1if (i <= j);
JNBE/JA若不低于等于则跳转;若高于则跳转jump if not below equal;jump if aboveZF=0或CF=0if (i > j);
JL/JNGE若小于则跳转;若不大于等于则跳转jump if less;jump if not greater equalSF != OFif (si < sj);
JNL/JGE若不小于则跳转;若大于等于则跳转;jump if not less;jump if greater equalSF = OFif (si >= sj);
JLE/JNG若小于等于则跳转;若不大于则跳转jump if less equal;jump if not greaterZF != OF 或 ZF=1if (si <= sj);
JNLE/JG若不小于等于则跳转;若大于则跳转jump if not less equal;jump if greaterSF=0F 且 ZF=0if(si>sj)

更详细参考:https://www.jb51.net/article/178949.htm

寻址公式

如果寻的地址超过32位(FFFFFFFF),则就取FFFFFFFF的值

公式一

[立即数]

读取内存的值:

MOV EAX,DWORD PTR DS:[0x1234FF]

向内存中写入数据

MOV DWORD PRT DS:[0x1234FF],EAX

获取内存编号

LEA EAX,DWORD PTR DS:[0x1234FF]

公式二[reg]

reg代表寄存器,可以是8个通用寄存器中的任意一个

读取内存的值

MOV ESP,DWORD PTR DS:[EBP]

向内存中写入数据

MOV DWORD PTR DS:[EBP],ESP

公式三[reg+立即数]

读取内存的值:

mov ecx ,0x1234FF

mov eax,dword ptr ds:[ecx+4]

向内存中写入数据:

mov edx,0x1234FF

mov dword ptr ds:[edx+0xC],0x87654321

获取内存编号:

lea eax,dword ptr ds:[edx+4] —eax和edx+4(地址)相等

mov eax,dword ptr ds:[edx+4] --eax和edx+4(数值)相等

公式四[reg+reg*{1,2,4,8}]

读取内存的值:

MOV EAX,1234FF

MOV ECX,2

MOV EDX,DWORD PTR DS:[EAX+EDX*4]

向内存中写入数据

MOV EAX,1234FF

MOV ECX,2

MOV DWORD PTR DS:[EAX+ECX*2],87654321

获取内存编号:

LEA EAX,DWORD PTR DS:[EAX+ECX*4]

公式五[reg+reg*{1,2,4,8}+立即数]

读取内存的值:

MOV EAX,1234FF

MOV ECX,2

MOV EDX,DWORD PTR DS:[EAX+EDX*4+1]

向内存中写入数据

MOV EAX,1234FF

MOV ECX,2

MOV DWORD PTR DS:[EAX+ECX*2+1],87654321

获取内存编号:

LEA EAX,DWORD PTR DS:[EAX+ECX*4+1]

堆栈

Top栈顶,Base栈底

ESP存栈顶指针,EBP栈底

压入数据

MOV EBX,1234FF BASE

MOV EDX.1234FF TOP

栈顶减4

方式一:

MOV DWORD PTR DS:[EDX-4],0xAAAAAAAA

SUB EDX,4

方式二:

SUB EDX,4

MOV DWORD PTR DS:[EDX],0xBBBBBBBB

方式三:

MOV DWORD PTR DS:[EDX-4],0xCCCCCCCC

LEA EDX,DWORD PTR DS:[EDX-4]

方式四:

LEA EDX,DWORD PTR DS:[EDX-4]

MOV DWORD PTR DS:[EDX],0xEEEEEEEE

读取数据

方式一:通过base加偏移来读取

读第一个压入的数据:

MOV ESI,DWORD PTR DS:[EBX-4]

读第四个压入的数据:

MOV ESI,DWORD PTR DS:[EBS-0x10]

方式二:通过Top加偏移来读取

读第二个压入的数据:

MOV EDI,DWORD PTR DS:[EDX+4]

读第三个压入的数据:

MOV EDI,DWORD PTR DS:[EDX+8]

弹出数据

栈顶加4

方式一:

MOV ECX,DWORD PTR DS:[EDX]

LEA EDX,DWORD PTR DS:[EDX+4]

方式二:

MOV ESI,DWORD PTR DS:[EDX]

ADD EDX,4

方式三:

LEA EDX,DWORD PTR DS:[EDX+4]

MOV ESI,DWORD PTR DS:[EDX-4]

标志寄存器

31-12OFDFIFTFSFZF0AF0PF1CF
11109876543210

CF :进位标志(Carry Flag)

如果运算结果的最高位(先要知道数据宽度)产生了一个进位或借位,那么其值为1,否则为0

MOV AL.0xEF ADD AL,2

MOV AL,0xFF ADD AL,2

若算术产生的结果在最高有效位(most-significant bit)发生进位或者借位则将其置1 反之清零

这个标志通常用来指示无符号证书运算的溢出状态

宽度溢出位。只要容器内放不下就会发生变化

PF :奇偶标志(Padity Flag)

用于反映运算结果(最低有效字节位,最后一个字节)中“1”的个数的奇偶性,如果为偶数,则PF的值为1,否则为0

MOV AL,3

ADD AL,3

ADD AL,2

如果结果的最低有效字节 最后一个字节(least-significant byte)包含偶数个1位则该位置1,否则清零

利用PF可进行奇偶校验检查

需要传输1100 1110,数据中含5个1,所以其奇校验位位0,同时吧1100 1110传输给接收方,

接收方收到数据后再一次计算奇偶性,1100 1110中仍然含有5个1,所以接收方计算出的奇偶验位还是0,与发送方一致,表示在此次传输过程中未发生错误

AF:辅助进位标志(Auxiliary Carry Flag)

在发生下列情况时,AF为1,否则为0

1.在字操作时,发生低字节向高字节进位或借位时

2.在字节操作时,发生低4位向高4位进位或借位时

MOV EAX,0x55EEFFFF ADD EAX,2

MOV AX,5EFF ADD EAX,2

MOV AL,4E ADD AL,2

ZF:零标志(Zero Flag)用的最多

反映运算结果是否为0

如果运算结果为0,则ZF值为1,否则为0

XOR EAX,EAX

mov eax,2

sub eax,2

SF:符号标志(Sign Flag)

用来反映运算结果的符号位,它与运算结果的最高位相同

MOV AL,7L

ADD AL.2

OF:溢出标志(Overflow Flag)

用于反映有符号数加减运算所得的结果是否溢出

如果运算结果超过当前运算位数所能表示的范围,则称为溢出,OF值为1,否则为0

OF和CF区别

进位标志(CF)表示无符号数运算结果是否超出范围

溢出标志(OF)表示有符号数运算结果是否超出范围

溢出主要是给有符号运算使用的,有如下规律:

正+正=正 如果结果是负数,则说明有溢出

负+负=负 如果结果是正数,则说明有溢出

正+负 永远不会有溢出

1、无符号、有符号都不溢出

MOV AL,8

ADD AL,8

2、无符号溢出,有符号不溢出

MOV AL,0FF

ADD AL,2

3、无符号不溢出,有符号溢出

MOV AL,7F

ADD AL,2

4、无符号、有符号都溢出

MOV AL,0FE

ADD AL,80

DF[Diretion Flag]

这个方向标志控制字符串指令(MOVS,CMPS,SCAS,LODS以及STOS)。设置DF标志是的串指令自动递减(从高地址向低地址方向处理字符串),清楚该标志则是的串指令自动递增

STD以及CLD指令分别用户设置以及清除DF标志

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值