学习过程的简单记录,留在这里方便以后查找
一,寄存器
1,ESP指向栈的最顶端
EIP指向将要执行的指令
有EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI和EIP等,它们都被称为32位寄存器。
AX包含的值为EAX的后4位数字。还可继续分为AL和AH
2,标志寄存器
这里的标志分为C,P,A,Z,S,T,D和O
1)O标志(溢出标志)溢出标志在当操作改变了符号位,返回错误值时被设置。看一下以下在OllyDbg中的例子,同样使用CrueHead‘a的CrackMe。
我们按照前面讲述的方法将EAX的值改为7FFFFFFF,即最大的正数。
2)A标志(辅助进位标志)
3)P标志(奇偶标志)
如果指令的结果用二进制表示,该二进制数中的1的总个数为偶数时,P标志被设置。
例如:1010,1100,1111000.
4)Z标志(零标志)
这是在Cracking过程中最著名最有用的一个标志。当运算产生的结果为0时被设置。
5)S标志(符号标志)
这个标志在运算结果为负时设置为1
6)C标志进位标志
(无符号运算的结果)在超过最大数值时设置,可能是寄存器的值
二,数学指令
1,INC 加一 ,DEC 减一
2,ADD指令有两个操作数,相加后的结果存放到第一个操作数中。
ADD EAX,1等价于INC EAX。ADD也可将两个寄存器相加
3,ADC(带进位的加法)
在这种情况下,两个操作数的和加上进位标志的值,结果存放到第一个操作数中。
4,SUB
它将第一个操作数减去第二个操作数的值存放到第一个操作数中
SUB EAX,DWORD PTR DS:[405000]
寄存器EAX减去405000内存单元的值,并将结果保存在EAX中。
5,SBB
该指令跟ADC正好相反,它计算两个操作数的差值,并且还要减去进位标志,结果存放到第一个操作数中。
6,MUL(无符号数的乘法)
有两种乘法,第一个种是MUL,这种是无符号数乘法,只有一个操作数,另一个操作数是EAX,结果存放到EDX:EAX中。
例如:
MUL ECX
这里是无符号数EAX,ECX相乘,结果存放到EDX:EAX中。
一部分保存在EAX中,另一部分保存在EDX中,EAX容纳不下高位的8,所以存放到EDX中了,也就是说,大小是单个寄存器的两倍。
7,IMUL(有符号数的乘法),IMUL还允许使用多个操作数,这是与MUL不同的地方。
尽管在默认情况下是使用EAX和EDX寄存器,但是我们还可以指定其他的数据源以及目标多达三个操作数
IMUL EBP, DWORD PTR [ESI+74], FF800002
ESI+74内存单元的值乘以FF800002,并且将结果存储到EBP中
8,DIV(无符号除法)/IDIV(有符号除法)
DIV只有一个操作数,该操作数必须是无符号数,结果存放到EDX:EAX中。
IDIV指令经常被使用。如果是一个操作数的话,那么它和DIV类似,只不过操作数是有符号的,结果依然保存在EDX:EAX中。两个操作数的情况,第一个操作数除以第二个操作数,结果存放到第一个操作数中。
三个操作数的情况,第二个操作数除以第三个操作数,结果存放到第一个操作数中。
9,XADD(交换并相加)
正如你所猜想的一样,这个指令其实就是XCHG和ADD两个简单指令的组合。
10,NEG
该指令的目的是将操作数的符号取反,即如果我们有一个32位的16进制数,用NEG操作以后,结果就会取反。
三,操作指令
1,NOP 无操作 滑行指令 nop指令只占一个字节 替换push等指令时要用两个nop
2,PUSH 将操作数压入栈中
PUSH [401000] 和PUSH 401000 不一样
读/写的内容在内存中倒序放置是处理器的特点之一
3,POP
POP指令是出栈:它会取出堆栈顶部的第一个字母或者第一个值,然后存放到指定的目标地址内存单元中。
例如,POP EAX从栈顶中取出第一个值存放到EAX中,随后的一个值随即变成栈顶。
4,PUSHAD
PUSHAD指令把所有通用寄存器的内容按一定顺序压入到堆栈中,
PUSHAD也就相当于’PUSH EAX,PUSH ECX,PUSH EDX,PUSH EBX,PUSH ESP,PUSH EBP,PUSH ESI, PUSH EDI’。
5,POPAD
该指令与PUSHAD正好相反,它从堆栈中取值,并将它们放到相应的寄存器中。
POPAD等价于“POP EDI,POP ESI,POP EBP,POP ESP,POP EBX,POP EDX,POP ECX,POP EAX”。
也有这样的用法
PUSHA 等价于 ‘PUSH AX, CX, DX, BX, SP, BP, SI, DI‘。
POPA 等价于 ‘pop DI, SI, BP, SP, BX, DX, CX, AX‘。
6,MOV
该指令将第二个操作数赋值给第一个操作数,例如:
MOV EAX, EBX
MOVSX (带符号扩展的传送指令)
第二个操作数可能一个寄存器也可能是内存单元,第一个操作数的位数比第二个操作数多,第二个操作数的符号位填充第一个操作数剩余部分。
16位数的范围是0000到FFFF。0000到7FFF是正数,8000到FFFF是负数。
如果是负数,填充F,正数填充0
MOVZX (带0扩展的传送指令)
MOVZX类似于前面的语句,但是这种情况下,剩余的部分不根据第二个操作数的正负来进行填充。剩余的部分总是被填充为0。
7,XCHG (交换 寄存器/内存单元 和 寄存器)
也可以使用这个指令来交换寄存器和内存单元的值,
8,LEA (取地址指令)
类似于MOV指令, 但是第一个操作数是一个通用寄存器,并且第二个操作数是一个内存单元。当计算的时候要依赖于之前的结果的话,那么这个指令就非常有用
四,比较和跳转指令
1,CMP
该指令是比较两个操作数,实际上,它相当于SUB指令,但是相减的结果并不保存到第一个操作数中。只是根据相减的结果来改变零标志位的,当两个操作数相等的时候,零标志位置1。
后面可以跟上JZ指令,置1就跳转为成功。
2,TEST逻辑比较
两个操作数进行与操作 结果不保存 但是会改变相应标志位(比如说,SF,ZF,PF标志位)
3,JUMPS 跳转
JMP – 跳转
JE, JZ – 结果为零则跳转 (零标志位是Z Z=1跳转)
JNE, JNZ – 结果不为零则跳转
JS – 结果为负则跳转 (符号标志位 S=1 结果为负)
JNS – 结果不为负则跳转
JP, JPE – 结果中1的个数为偶数则跳转 (奇偶校验位P =1)
JNP, JNPE – 结果为1的个数为奇数则跳转
JO – 结果溢出了则跳转
JNO – 结果没有溢出则跳转
JB, JNAE – 小于则跳转 (无符号数)
JNB, JAE – 大于等于则跳转 (无符号数)
JBE, JNA – 小于等于则跳转 (无符号数)
JNBE, JA – 大于则跳转(无符号数)
JL, JNGE – 小于则跳转 (有符号数)
JNL, JGE – 大于等于则跳转 (有符号数)
JLE, JNG – 小于等于则跳转 (有符号数)
JNLE, JG – 大于则跳转(有符号数)