失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > OD汇编指令集(不断更新)

OD汇编指令集(不断更新)

时间:2021-05-12 04:38:56

相关推荐

OD汇编指令集(不断更新)

一、快捷键

F7 执行一行代码,遇到 CALL 等子程序时会进入其中,进入后首先会停留在子程序的第一条指令上。

F8 执行一行代码,遇到 CALL 等子程序不进入其代码。

F2 在显著行设置断点,再次按 F2 删除断点。

F9 F9运行调试程序,直到遇到断点停止运行,Debug->Run。

F12 临时暂停程序,Debug-> Pause。

二、寄存器

ESP 指向堆栈最顶端的地址。

EIP 指向当前将要执行的指令的地址。

EAX ECX EDX EBX ESP EBP ESI EDI EIP——32位寄存器

EAX=0x12345678 AX=0x5678——16位寄存器 AH=0x56,AL=0x78

O/欧 溢出标志

A 辅助进位标志/不关心

P 奇偶标志,指令的结果用二进制表示,该二进制数中1的总个数为偶数时,P标志被设置。

Z 零标志,当运算产生的结果为 0 时被设置。

S 符号标志,这个标志在运算结果为负时设置为 1。

C 进位/借位标志,(无符号运算的结果)在超过最大数值时设置为 1 ,可能是寄存器的值。

T,D 标志和其它

三、汇编指令

指令

1.? 寄存器或数值——查看寄存器内容,显示数值的十进制以及ASCII码

NOP指令

2.替换指令:右键->Assemble 或 Space

3.在数据窗口查看指定内存数据:右键->“Go to”->“Expression”->输入地址

4.撤销修改的指令:选择被替换的几行->右键->“Undo Selection”

PUSH指令

5.push 401008

push [401008];内存的倒序存储 = push DWORD PTR DS:[401008]

不明确规定,OD认为都是4个字节内存,DWORD

POP指令

6.POP EAX——从栈顶中取出第一个值存放到EAX中,随后的一个值随即变成栈顶。

PUSHAD指令

7.PUSHAD指令把所有通用寄存器的内容按一定顺序压入到堆栈中

=push eax, push ecx, push edx, push ebx, push esp, push ebp, push esi, push edi

POPAD指令

8.POPAD指令与PUSHAD正好相反,它从堆栈中取值,并将它们放到相应的寄存器中

=pop edi, pop esi, pop esp, pop ebx, pop edx, pop ecx, pop eax

MOV指令

9.该指令将第二个操作数赋值给第一个操作数,例如:

MOV EAX, EBX;EBX值赋值给EAX。

mov [405000],eax——报错,不能直接写入内存

MOVSX(带符号扩展的传送指令)

10.第二个操作数可能一个寄存器也可能是内存单元,第一个操作数的位数比第二个操作数多,第二个操作数的符号位填充第一个操作数剩余部分

eax=00401008,bx=e000

movsx eax,bx

eax=ffffe000,bx=e000

16位范围,0000-7fff 正数 8000-ffff 负数

MOVZX(带0扩展的传送指令)

11.MOVZX类似于前面的语句,但是这种情况下,剩余的部分不根据第二个操作数的正负来进行填充。我们这里不提供范例,因为和上面是相似的,剩余的部分总是被填充为0。

LEA(取地址指令)

12.第一个操作数是一个通用寄存器,并且第二个操作数是一个内存单元。

lea eax,dword ptr ds:[ecx+38]

ecx=12ffb0

实质是 eax=ecx+38

eax=12ffe8

XCHG(交换 寄存器/内存单元 和 寄存器)

13.该指令交换两个操作数的值;也可以使用这个指令来交换寄存器和内存单元的值

XGHG EAX,ECX

四、数学指令

INC 和 DEC指令

14.INC EAX ; 使EAX+1

DEC EAX ; 使EAX-1

INC DWORD PTR DS:[405000]

INC WORD PTR DS:[405000]

ADD指令

ADD指令有两个操作数,相加后的结果存放到第一个操作数中。ADD EAX,1等价于INC EAX。

ADC指令(带进位的加法)

15.两个操作数的和加上进位标志的值,结果存放到第一个操作数中。

SUB指令

16.这个指令与ADD刚好相反-它将第一个操作数减去第二个操作数的值存放到第一个操作数中。

SBB指令

17.该指令跟ADC正好相反,它计算两个操作数的差值,并且还要减去进位标志,结果存放到第一个操作数中。

MUL(无符号数的乘法)

18.有两种乘法,第一个种是MUL,这种是无符号数乘法,只有一个操作数,另一个操作数是EAX,结果存放到EDX:EAX中

MUL ECX ; EDX:EAX=EAX*ECX

IMUL(有符号数的乘法)

19.IMUL指令用法类似于MUL。操作数可以有1个 2个 或 3个

IMUL ECX; 该指令将有有符号数ECX乘以EAX,结果存放到EDX:EAX中。

IMUL EDX, DWORD PTR [EBP-18]; EDX x [EBP-18] -> EDX

IMUL EBP, DWORD PTR [ESI+74],FF800002; [ESI+74] x FF800002 -> EBP

DIV/IDIV指令

20.这两个指令反别与MUL和IMUL相反。

DIV只有一个操作数,该操作数必须是无符号数,结果存放到EDX:EAX中。

IDIV指令经常被使用。

如果是一个操作数的话,那么它和DIV类似,只不过操作数是有符号的,结果依然保存在EDX:EAX中。

两个操作数的情况,第一个操作数除以第二个操作数,结果存放到第一个操作数中。

三个操作数的情况,第二个操作数除以第三个操作数,结果存放到第一个操作数中。

1- div除法指令

(1) 除数: 有8位和16位两种,在一个寄存器或内存单元中.

(2) 被除数: 默认放在AX和DX或AX中

除数为8位, 被除数为16位, 默认在AX中存放.

除数为16位, 被除数为32位, 在DX或AX中存放. AX存放低16位,DX存放高16位.

(3) 结果

除数为8位, 则AL存储除法操作的商, AH存放余数

除数为16为, 则AX存储除法操作的商, DX存放余数

XADD指令(交换并相加)

21.这个指令其实就是XCHG和ADD两个简单指令的组合,相加的结果放到第1个操作数中。

NEG指令

22.取补指令,负数的补码是取反再加1,正数的补码是它本身;

逻辑指令

逻辑指令有两个操作数,两操作数按位运算,并将结果存放到第一个操作数中。

AND OR XOR(同为零,异为一) NOT(按位取反)

ebx=38 neg ffffffc8

neg != not

五、比较和条件跳转指令

CMP指令(判断2个操作数是否相等)

23.该指令是比较两个操作数,实际上,它相当于SUB指令,但是相减的结构并不保存到第一个操作数中。

只是根据相减的结果来改变零标志位的,当两个操作数相等的时候,零标志位 Z 置1。

符号标志位 S 是比较第一个操作数是否大于第二个操作数。

CMP EAX,ECX; 若EAX > ECX,则Z=0,S=0

若EAX < ECX,则Z=0,S=1

CMP AX,WORD PTR DS:[405000]

CMP AL,BYTE PTR DS:[405000]

TEST(逻辑比较)

24.该指令在一定程序上和CMP指令时类似的,两个数值进行与操作,结果不保存,但是会改变相应标志位(比如说,SF,ZF,PF标志位),程序可以根据结果来决定是否跳转到相应的分支。

TEST EAX,EAX; 用这个指令,可以确定EAX是否等于0。

逻辑指令

JMP - 跳转

JE, JE - 结果为零则跳转 Z=1

JNE, JNZ - 结果不为零则跳转

JS - 结果为负则跳转 S=1

JNS - 结果不为负则跳转

JP, JPE - 结果中1的个数为偶数则跳转 P=1

JNP, JNPE – 结果为1的个数为奇数则跳转

JO - 结果溢出了则跳转 O=1

JNO – 结果没有溢出则跳转

JB, JNAE – 小于则跳转(无符号数) 进位/借位标志位 C=1

JNB, JAE – 大于等于则跳转(无符号数) C=0

JBE, JNA – 小于等于则跳转(无符号数) C=1 或 Z=1

JNBE, JA – 大于则跳转(无符号数) C=0 且 Z=0

JL, JNGE – 小于则跳转(有符号数) S = 1

JNL, JGE – 大于等于则跳转(有符号数)

JLE, JNG – 小于等于则跳转(有符号数) Z=1 或者 S!=OF

JNLE, JG – 大于则跳转(有符号数) Z=0 或者 S=OF

SHR - 逻辑右移指令

SAR - 算术右移指令

六、循环 字符串指令和寻址方式

LOOP指令(循环指令)

25.通常循环执行的次数放在ECX中,LOOP指令执行时:

a.ECX = ECX-1

b.判断ECX中的值,不为零则转移到标号处执行程序,如果为零,则向下执行。

LOOPZ,LOOPE 重复循环,直到零标志位Z置1

LOOPNZ,LOOPNE 重复循环,直到零标志位Z清0

串操作

MOVS指令(另一种形式MOVSD)

26.该指令是从一个地址向另一个地址复制数据。源地址保存在ESI寄存器中,目的地址保存在EDI寄存器中。

MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]

MOVSW——拷贝两个字节

MOVSB——拷贝一个字节

拷贝的方向取决于方向标志位D,D=0时从后往前拷贝。

REP指令(从一个地址单元拷贝任意数目的字节内容到另一个地址单元)

27.该指令可做为前面介绍的一些指令的前缀,尤其是MOVS指令,该前缀表示当前指令需要执行的次数ECX,每次循环计数器ECX的值递减1,和前面介绍的循环一样。

REP MOVS不一定拷贝是4个字节,它拷贝的大小为【每次拷贝的大小 * ECX】,源指针ESI和目的指针EDI每次递增4或者递减4(递增或递减取决于方向标志位D)。

REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]

注:MOVS指令不能将数据拷贝到没有写入权限的内存单元中,强制写入的话会引发异常。

类似指令:REPE/REPZ/REPNZ/REPNE

SCASB,SCASW, SCASD。这三个指令把al ax eax中的值同edi寻址到的目标内存中的字节或字或双字相比较。(即al,ax,eax与edi寻址后的内存值进行比较)这些指令在一个长字符串或数组中查找一个值的时候特别有用。如果使用REPE(或REP 前缀),REP前缀是当ecx寄存器>0时,重复。 而REPE前缀是零标志位(zf=1), 并且ecx>0时重复。

REPNE,这个前缀刚好和REPE是反的。 也就是它是如果我们的ZF=0且ECX>0进行重复,只要满足这两个条件它就进行重复,如果不满足则不进行重复,所以REPNE一般我们用来扫描字符串。

(1) lodsb、lodsw:把DS:SI指向的存储单元中的数据装入AL或AX,然后根据DF标志增减SI

(2) stosb、stosw:把AL或AX中的数据装入ES:DI指向的存储单元,然后根据DF标志增减DI

(3) movsb、movsw:把DS:SI指向的存储单元中的数据装入ES:DI指向的存储单元中,然后根据DF标志分别增减SI和DI

(4) scasb、scasw:把AL或AX中的数据与ES:DI指向的存储单元中的数据相减,影响标志位,然后根据DF标志分别增减SI和DI

(5) cmpsb、cmpsw:把DS:SI指向的存储单元中的数据与ES:DI指向的存储单元中的数据相减,影响标志位,然后根据DF标志分别增减SI和DI

(6) rep:重复其后的串操作指令。重复前先判断CX是否为0,为0就结束重复,否则CX减1,重复其后的串操作指令。主要用在MOVS和STOS前。一般不用在LODS前。

上述指令涉及的寄存器:段寄存器DS和ES、变址寄存器SI和DI、累加器AX、计数器CX

涉及的标志位:DF、AF、CF、OF、PF、SF、ZF

LOOP指令

REP前缀也可以与LOOPS指令配合使用,他们会重复执行直到计数器ECX的值为0.

LODS 指令 :取字符串数据指令(Load String Instruction)

从源地址DS:SI所指向的内存单元开始,LODSB LODSW LODSD 取一个字节、字或双字,送入AL、AX或EAX中,并根据标志位DF对寄存器SI作相应增减。该指令的执行不影响任何标志位。

当方向标志位DF=0时,则SI自动增加1、2或4;DF=1时,SI自动减小1、2或4。

STOS指令 : 置字符串数据指令(Store String Instruction)

该指令是把寄存器AL、AX或EAX中的值存于以指针ES:[DI]所指向内存单元为起始的一片存储单元里,并根据标志位DF对寄存器DI作相应增减。该指令不影响任何标志位。

MOVS指令:字符串传送指令(Move String Instruction)

该指令是把指针DS:SI所指向的字节、字或双字传送给指针ES:DI所指向内存单元,并根据标志位DF对寄存器DI和SI作相应增减。该指令的执行不影响任何标志位。

CMPS指令

30.该指令比较ESI和EDI指向内存单元的内容,该指令执行的是算数减法运算。

CMPS DWORD PTR [ESI],DWORD PTR [EDI]

该指令影响零标志位Z,所以可以配合REPE/REPZ前缀指令使用,直到计数器ECX的值为0或者零标志位清0.

sete cl - 设置指令,根据ZF标志位来设置cl的值,如果ZF=1,则cl=1,否则cl=0;

七、断点

普通断点【B】——断点窗口

31.当我们设置断点后,OD会将对应指令处第一个字节指令替换成CC。但是为了不影响界面显示效果,OD会将CC显示为原字节。但是,我们可以在内存单元中读取出其真实的内容,并且可以在反调试中用此方法来检测断点。所以,我们设置的断点有时候莫名其妙的消失了不要感到奇怪,或许说这是调试器的本身的弱点吧。

内存断点

32.不能设置多个;不会出现【B】断点列表和其他的地址。

33.当我们对指定内存单元没有写权限,尝试写入的时候会触发异常,OD会拦截到这个异常,并中断下来,我们看到断下来的时候,OD已经将内存页的访问属性设置正常了。

34.对区段设置内存断点【M】,尝试执行当前代码段的任何一条指令都会触发内存访问断点。

比如对Kernel32.dll设置断点,则调用该dll中的函数GetModuleHandleA会触发断点,并且执行GetModuleHandleA的每一条指令都会触发。

35.返回主程序模块:-Debug-Execute till user code,或者在函数返回指令处设置断点,中断下来后再按F7或F8单步到主程序代码中。

硬件断点(简称HBP)

36.硬件断点分为硬件执行断点(ON EXECUTION),硬件写入断点(ON WRITE),硬件访问断点(ON ACCESS)3种,OD中最多设置4个硬件断点。

硬件执行断点和普通的CC断点作用一样,但硬件执行断点并不会将指令首字节修改为CC,所以更难检测。

右键-Breakpoint-Hardware,on execution

HE 401013

单个硬件写入断点或者硬件访问断点可以设置1,2或者4个字节的长度,不论我们选择的数据范围有多大,只有前4个字节会起作用。

硬件访问/断点断在了触发硬件断点的下一条指令处。

条件断点

EAX==400000

37.条件断点实际上就是普通的CC断点,只不过该断点的触发需要满足设置的条件,如果满足设置的条件,那么程序就会中断下来,如果不满足条件的话,就和没有设置CC断点差不多。

条件记录断点【L】——日志窗口

38.通过设置该断点来记录下设置的条件的精确值。

我们给一个API函数设置条件记录断点,程序中有很多地方调用了这个API函数,通过该条件记录断点我们可以精确的记录程序中每处调用该API函数传递给它的内容。

如果程序中有大约100处调用了该API函数,你可以指定相应的条件,比如说返回地址。设置条件为[ESP] == 40137D,那么这100个函数调用中只有返回地址为40137D的会被记录下来。

如果觉得《OD汇编指令集(不断更新)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。