[原创]软件调试基础--01必备汇编基础
本文不是讲述汇编语言,而是讲述调试过程中,应该掌握的基本汇编指令,这样对后来的调试过程是有很大帮助。如果一点都不懂,软件调试将难以进行。汇编基础比较好的同学可以直接跳过本章。
实验环境:WIN7 + VS2008
1.mov指令
代码段:
int a = 0;
__asm
{
mov a,10;//相当于 mov dword ptr[a], 10;
}
说明:给变量a赋值。(将10写入变量a所在地址处)
代码段:
int a = 0;
__asm
{
mov eax, 100;//将100写入eax寄存器
mov a, eax;//将eax寄存器中的内容,写入变量a所在地址处
}
说明:将100赋值给eax寄存器,并且将eax寄存器的值赋值给变量a。
代码段:
int a = 0;
int *p = &a;
__asm
{
mov eax, dword ptr
;//将指针变量p本身所在地址赋值给eax
mov dword ptr[eax], 100;//将100写入eax所表示的地址处
}
说明:通过p指针,对变量a进行赋值。
2.xor指令
代码段:
__asm
{
xor eax,eax;
}
说明:异或操作,将结果赋值给第一个操作数。此代码为给eax清零。
3.lea指令
代码段:
__asm
{
lea eax,[a];
}
说明:将a变量所在地址,放在eax寄存器中。
4.rep stos指令
代码段:
__asm
{
lea edi,[ebp-0C0h] ;
mov ecx,30h ;
mov eax,0CCCCCCCCh ;
rep stos dword ptr es:[edi];
}
说明:重复执行ecx次,将eax值写入es:[edi]中,每执行一次,ecx减一,直到ecx为0。此段代码为给栈变量初始化默认值为CC。
5.add和sub指令
代码段:
_asm
{
add esp,4;
}
说明:寄存器esp的值加4,此操作含义为清理4字节栈空间,通常位于函数尾部
代码段:
__asm
{
sub esp,4;
}
说明:寄存器esp值减去4,此操作含义为在栈空间中分配4个字节。
6.push和pop指令
代码段:
__asm
{
push eax;
}
说明:将eax压栈,通常用于函数参数传递。
__asm
{
pop eax;
}
说明:取出esp指向的栈顶头4字节内容,放入eax。
7.call和ret
说明:call实际上是call+jmp指令,(想想为什么设计成call+jmp,而不是直接jmp?);ret为函数返回指令,ret 4;表示ret同时esp+4,也就是释放栈空间。
实际上call的是一个地址,而这个地址上是jmp指令,我们知道call实际上是push retaddr + jmp,而跳过去的地方实际上是一个函数地址表,再次jmp才真的进入函数的开始。这个过程我们可以在debug版本的程序中,反汇编加以验证。
但是在某些情况下,有些函数调用并不是call,而是直接jmp的,这个就跟优化有关系了。
8.cmp和jmp、jnz、jz
代码段:
int a = 0;
int b = 0;
__asm
{
mov eax,1;
mov ebx,1;
mov ecx,2;
cmp eax,ebx;
jz X1;
cmp eax,ecx;
jnz X2;
X1:
mov a,10;
X2:
mov b,20;
}
说明:cmp为比较指令,当cmp操作数相等时,jz将被执行;如果cmp操作数不相等时,jnz将被执行。jmp为无条件跳转。
汇编指令实际上还有很多,这些比较常用。如果对汇编指令一无所知,本部分最好自己亲自在VS中尝试几次。如有遗忘,还可以翻开此文查阅。
