首页 > 代码库 > OllyDbg之汇编语言回顾

OllyDbg之汇编语言回顾

本文从http://bbs.pediy.com/showthread.php?t=184658&highlight=OllyDbg+Cracking+使用+从零+零开+开始+始摘录整理

一些标志寄存器 

O标志(溢出标志)高位溢出

 反映有符号数加减运算所得结果是否溢出。当指令的结果超出了它可能存取的最大值,如果运算结果超过当前运算位数所能表示的范围,则称为溢出,OF的值被置为1,否则,OF的值被清为0

 A标志(辅助进位标志)

 P标志(奇偶标志) 

 当指令结果的二进制格式含有偶数个1时,被设置。

 Z标志(零标志)

 当运算产生的结果为0时被设置。

 S标志(符号标志)

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

 C标志进位标志

把参与运算的数当作无符号数处理当运算结果的最高位发生进位(加法)或借位(减法)时,进位标志置1,即CF=1;否则CF=0。

 

标志被设置,意思是说使其等于1,被清除,则使其等于0。

 

 

汇编指令

NOP(无操作)
运行这条指令不会对寄存器,内存以及堆栈造成任何影响,英文单词的意思是”无操作”,也就是说,它没有特殊的用途

PUSH 

PUSH指令-将操作数压入堆栈中。

POP 
POP指令是出栈:它会取出堆栈顶部的第一个字母或者第一个值,然后存放到指定的目标地址内存单元中

PUSHAD 
PUSHAD指令把所有通用寄存器的内容按一定顺序压入到堆栈中,PUSHAD也就相当于’PUSH EAX,PUSH ECX,PUSH EDX,PUSH EBX,PUSH ESP,PUSH EBP,PUSH ESI, PUSH EDI’。

POPAD 
该指令与PUSHAD正好相反,它从堆栈中取值,并将它们放到相应的寄存器中。POPAD等价于“POP EDI,POP ESI,POP ESP,POP ESP,POP EBX,POP EDX,POP ECX,POP EAX”。

MOV 
该指令将第二个操作数赋值给第一个操作数

 

MOV AL, CL
这条指令时将CL的值赋值给AL

MOV DWORD PTR DS:[400500],EAX    

将EAX中的值给一个双字节的内存单元,内存单元中数值以小端模式存储

MOV AX,WORD PTR DS:[405008]
将405008内存单元中的两个字节赋值给AX

MOVSX (带符号扩展的传送指令)
第二个操作数可能一个寄存器也可能是内存单元,第一个操作数的位数比第二个操作数多,第二个操作数的符号位填充第一个操作数剩余部分。 

MOVZX (带0扩展的传送指令)
MOVZX类似于前面的语句,但是这种情况下,剩余的部分不根据第二个操作数的正负来进行填充。

LEA (取地址指令)
类似于MOV指令, 但是第一个操作数是一个通用寄存器,并且第二个操作数是一个内存单元。操作数仅仅是内存单元的地址,而不是里面的内容。

如 LEA EAX,DWORD PTR DS:[ECX+38]DWORD PTR DS:[ECX+38] 指内存地址

 

XCHG (交换 寄存器/内存单元 和 寄存器) 
该指令交换两个操作数的值

 

算术汇编指令

INC和DEC
这两个指令分别是执行增加和减少的操作,如果是INC指令的话,就加1,如果是DEC指令的话,就减1。

 

ADD
ADD指令有两个操作数,相加后的结果存放到第一个操作数中。前一个可以为内存地址

ADC(带进位的加法)
在这种情况下,两个操作数的和加上进位标志的值,结果存放到第一个操作数中。加完之后进位标志C置位1

 

SUB SUBB类似

 

MUL(无符号数的乘法)
有两种乘法,第一个种是MUL,这种是无符号数乘法,只有一个操作数,另一个操作数是EAX,结果存放到EDX:EAX中。MUL ECX
这里是无符号数EAX,ECX相乘,结果存放到EDX:EAX中。

 

IMUL(有符号数的乘法)
IMUL指令用法类似于MUL。
IMUL ECX 
该指令将有有符号数ECX乘以EAX,结果存放到EDX:EAX中。

 

DIV(无符号除法)/IDIV(有符号除法)类似

XADD(交换并相加)
正如你所猜想的一样,这个指令其实就是XCHG和ADD两个简单指令的组合。
XADD EAX,ECX

相加的结果是存放到第一个操作数中的。

 

NEG 
该指令的目的是将操作数的符号取反,即如果我们有一个32位的16进制数,用NEG操作以后,结果就会取反。

AND 按位与
OR 按位或
NOT 按位取反。
XOR 按位异或

 

比较

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

若结果为负,S标志(符号标志)位置1。,CMP指令还允许寄存器与BYTE,WORD,DWORD类型的内存单元的值做比较。

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

条件跳转

JMP – 跳转 
JE, JZ – 结果为零则跳转
JNE, JNZ – 结果不为零则跳转 
JS – 结果为负则跳转
JNS – 结果不为负则跳转 
JP, JPE – 结果中1的个数为偶数则跳转 
JNP, JNPE – 结果为1的个数为奇数则跳转 
JO – 结果溢出了则跳转 
JNO – 结果没有溢出则跳转
JB, JNAE – 小于则跳转 (无符号数)
JNB, JAE – 大于等于则跳转 (无符号数)
JBE, JNA – 小于等于则跳转 (无符号数)
JNBE, JA – 大于则跳转(无符号数)
JL, JNGE –  小于则跳转 (有符号数)
JNL, JGE – 大于等于则跳转 (有符号数)
JLE, JNG – 小于等于则跳转 (有符号数)
JNLE, JG – 大于则跳转(有符号数)

 

JMP 
这是一个无条件跳转指令,即总是跳转到指定的地址修改EIP

JE或者JZ
这两个条件跳转指令是等价的,只是书写的形式不同而已。我们可以看到零标志位Z被置1则跳转。

JNE或JNZ
这条指令与上面一个指令刚好相反:如果零标志位Z为0则跳转,即,要求操作的结果非零。

JS(smaller)
从上面的表中可以看出,当比较的结果为负时将跳转,即,按前面的例子的话就是EAX小于ECX。

JNS
这个跳转指令与JS刚好相反。当零标志位S为0的时候跳转,也就是说之前例子中,EAX大于ECX的时候跳转。

JP或JPE 
这个跳转指令时当奇偶标志位P置1的时候才会发生,也就是比较的结果中1的个数要是偶数,则跳转

JNP 或JNPE
这条指令刚好与上一条指令刚好相反,

JO
当发生溢出时,即溢出标志位O置1的时候跳转。
JNO
跟上一条指令相反,这里是当溢出标志位O为0时跳转,即溢出没有发生时。

JB
如果第一个操作数小于第二个操作数的时候跳转。和JS的区别在于JS只检查S符号标志位,而JB检查C进位标志位(由C标志位是对无符号数操作的特性可知,JB只能用于判断两个无符号数的大小)。

JNB
和JB指令相反,这个指令是当进位/借位标志位为0的时候跳转,也就是说,结果为正的时候跳转。在前面的例子中,因为EAX小于ECX,所以不会发生跳转。

JBE
这个指令时小于或者等于的时候跳转,这是判断两个标志位的,当进位/借位标志位置1或者零标志位Z置1的时候将发生跳转,也就是说,EAX要小于或者等于ECX才会发生跳转。

JL
这个指令当小于的时候跳转,但是与前面的JB稍微有点不同。这个指令根据符号标志位S来决定是否跳转(和JS一样?傻傻分不清楚)

OllyDbg之汇编语言回顾