首页 > 代码库 > 加壳学习笔记(二)-汇编基础
加壳学习笔记(二)-汇编基础
堆栈平衡
PUSH,POP
功能: 把操作数压入或取出堆栈
语法: PUSH 操作数 POP 操作数
格式: PUSH r PUSH M PUSH data POP r POP m
PUSHF,POPF,PUSHA,POPA
功能: 堆栈指令群
格式: PUSHF POPF PUSHA POPA
ADD,ADC
功能: 加法指令
语法: ADD OP1,OP2 ADC OP1,OP2
格式: ADD r1,r2 ADD r,m ADD m,r ADD r,data
影响标志: C,P,A,Z,S,O
SUB,SBB
功能:减法指令
语法: SUB OP1,OP2 SBB OP1,OP2
格式: SUB r1,r2 SUB r,m SUB m,r SUB r,data SUB m,data
影响标志: C,P,A,Z,S,O
INC,DEC
功能: 把OP的值加一或减一
语法: INC OP DEC OP
格式: INC r/m DEC r/m
影响标志: P,A,Z,S,O
MUL,IMUL
功能: 乘法指令
语法: MUL OP IMUL OP
格式: MUL r/m IMUL r/m
影响标志: C,P,A,Z,S,O(仅IMUL会影响S标志)
DIV,IDIV
功能:除法指令
语法: DIV OP IDIV OP
格式: DIV r/m IDIV r/m
CBW,CWD
功能: 有符号数扩展指令
语法: CBW CWD
AAA,AAS,AAM,AAD
功能: 非压BCD码运算调整指令
语法: AAA AAS AAM AAD
影响标志: A,C(AAA,AAS) S,Z,P(AAM,AAD)
DAA,DAS
功能: 压缩BCD码调整指令
语法: DAA DAS
影响标志: C,P,A,Z,S
SHR,SHL,SAR,SAL
功能: 移位指令
语法: SHR r/m,data/CL SHL r/m,data/CL SAR r/m,data/CL SAL r/m,data/CL
影响标志: C,P,Z,S,O
ROR,ROL,RCR,RCL
功能: 循环移位指令
全部跳转语句:
Jxx - Jump Instructions Table
Mnemonic Meaning Jump Condition
JA Jump if Above CF=0 and ZF=0
JAE Jump if Above or Equal CF=0
JB Jump if Below CF=1
JBE Jump if Below or Equal CF=1 or ZF=1
JC Jump if Carry CF=1
JCXZ Jump if CX Zero CX=0
JE Jump if Equal ZF=1
JG Jump if Greater (signed) ZF=0 and SF=OF
JGE Jump if Greater or Equal (signed) SF=OF
JL Jump if Less (signed) SF != OF
JLE Jump if Less or Equal (signed) ZF=1 or SF != OF
JMP Unconditional Jump unconditional
JNA Jump if Not Above CF=1 or ZF=1
JNAE Jump if Not Above or Equal CF=1
JNB Jump if Not Below CF=0
JNBE Jump if Not Below or Equal CF=0 and ZF=0
JNC Jump if Not Carry CF=0
JNE Jump if Not Equal ZF=0
JNG Jump if Not Greater (signed) ZF=1 or SF != OF
JNGE Jump if Not Greater or Equal (signed) SF != OF
JNL Jump if Not Less (signed) SF=OF
JNLE Jump if Not Less or Equal (signed) ZF=0 and SF=OF
JNO Jump if Not Overflow (signed) OF=0
JNP Jump if No Parity PF=0
JNS Jump if Not Signed (signed) SF=0
JNZ Jump if Not Zero ZF=0
JO Jump if Overflow (signed) OF=1
JP Jump if Parity PF=1
JPE Jump if Parity Even PF=1
JPO Jump if Parity Odd PF=0
JS Jump if Signed (signed) SF=1
JZ Jump if Zero ZF=1
Clocks Size
Operands 808x 286 386 486 Bytes
Jx: jump 16 7+m 7+m 3 2
no jump 4 3 3 1
Jx near-label - - 7+m 3 4
no jump - - 3 1
- It‘s a good programming practice to organize code so the
expected case is executed without a jump since the actual
jump takes longer to execute than falling through the test.
- see JCXZ and JMP for their respective timings
JCXZ/JECXZ - Jump if Register (E)CX is Zero
Usage: JCXZ label
JECXZ label (386+)
Modifies flags: None
Causes execution to branch to "label" if register CX is zero. Uses
unsigned comparision.
Clocks Size
Operands 808x 286 386 486 Bytes
label: jump 18 8+m 9+m 8 2
no jump 6 4 5 5
JMP - Unconditional Jump
2.简单的call函数过程
1.參数入栈。返回地址入栈。
在一个栈帧里,call function的完整过程应该是这种。call调用的过程要经历两个过程,一个是首先把调用函数之前的指令的下一条指令地址压入栈中(push ebp),作为返回地址,也就是保存旧栈地址,接着会跳转到被调函数的地址入口。
呵呵,如今就是借此来恶补汇编哈。
2.代码区跳转。在运行被调函数的时候,为函数又一次开辟栈帧。(mov ebp,esp)这句的意思是将旧栈顶换为新栈的底,这里的新栈通常是由函数专属的哈, 以下就是用sub esp, xx 抬高栈顶,这个过程也就是被调函数局部变量从右向左依次入栈的过程。运行函数体的代码段,
3.栈帧调整。第一步是:保存当前栈的状态值。就是push ebp,我的理解就是这里实际上是入的系统栈,之所以要先使ebp入栈是要为了切割栈帧,告诉系统要截断旧栈帧,建立新栈帧。
第二步:将栈顶装入新的栈底,mov ebp,esp ,准备栈帧转换了,使用这句话的目的是建立新的空栈;第三步:sub esp,xx 就是抬高栈顶,sub是减嘛,就是向低地址扩展噻。栈顶的地址减小,用__stdcall约定的话,假设有三个參数1,2,3
则这里的入栈顺序为 push 3 ;push 2 ;push 1;这样依次參数入栈,完毕函数体入栈(就是将原来的栈顶作为新栈的栈底存在寄存器里,一般就是在系统栈上往上加。开辟完之后,首先call指令会跳转到该函数的入口地址。运行函数体,即将函数的变量依次压入栈中,再依次弹栈,最后返回调用该函数之前的栈地址,也就是上一次的栈顶,这里再进行栈顶的弹栈,正好就是上次调用的函数的调用点)。
4.跳转。当函数运行完毕后首先是保存返回值,通常将函数的返回值保存的EAX寄存器中,然后将当前的栈帧的数据一个个的弹出,直到栈底。实际的详细过程是在esp上加上当前栈帧的大小。减少栈顶,回收当前栈帧的空间,然后当前栈底的保存的前一个栈帧的ebp弹入ebp寄存器,恢复上一个栈帧,将函数返回地址弹给EIP寄存器。下一步依照函数返回地址(不太明确)继续运行母函数中函数调用点的下一个指令的操作:详细代码是:
add esp,xxx //减少栈顶
pop ebp //弹出栈底
retn //这条代码有两个作用,1.弹出当前栈顶元素,这时候已经是到了旧栈帧了。也就是弹出之前的保存指令位置的返回地址,到这里栈帧恢复工作完毕啦。然后让处理器取指令的跳转到原来的返回地址恢复调用前的代码区
加壳学习笔记(二)-汇编基础