VC++代码的汇编分析

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VC++代码的汇编分析相关的知识,希望对你有一定的参考价值。

VC++代码是最接近汇编指令的高级语言,为了更加准确和深刻理解VC++编码中所涉及的很多技术概念和编译器参数的含义,从汇编指令层面进行剖析和解读,有助于开发者更加准确、直观、深刻理解高级语言中很多概念和技术的真正含义,对程序优化和编码都有非常实用的重要价值。由于内容很多,我会分解为很多篇章进行解读实例。

从main入口开始分析,使用古老的VC6.0编译器编译,先从最简单的例子开始逐步扩展,便于大家逐步入门。

VC++源代码:

int main(int argc, char* argv[])

{
printf("Hello World!\n");
return 0;
}

最简单不过的代码了,看看汇编代码是什么呢?关于32位X86寄存器的基础知识,大家可以自己先上网看啦。

debug状态下无优化的汇编代码:

int main(int argc, char* argv[])
20: {
00401030 55          push ebp     ==保存EBP
00401031 8B EC        mov ebp,esp  ==保存ESP
00401033 83 EC 40      sub esp,40h      ==没有定义任何临时变量的情况下,默认预留64字节的栈内存空间
00401036 53           push ebx         ==保存EBX
00401037 56           push esi           ==保存ESI
00401038 57           push edi          ==保存edi
00401039 8D 7D C0       lea edi,[ebp-40h]  ==将栈顶地址放入EDI中
0040103C B9 10 00 00 00    mov ecx,10h    ==计数器16放入ECX
00401041 B8 CC CC CC CC    mov eax,0CCCCCCCCh ===初始值为指向INT3地址
00401046 F3 AB        rep stos dword ptr [edi]  ===初始化16个DWORD的栈空间
26: printf("Hello World!\n");
00401048 68 1C 20 42 00    push offset string "Hello World!\n" (0042201c)  ==将字符串参数地址入栈
0040104D E8 EE 00 00 00    call printf (00401140) ==调用函数
00401052 83 C4 04      add esp,4    ==恢复ESP
27: return 0;
00401055 33 C0        xor eax,eax  ==EAX清零
28: }
00401057 5F          pop edi   ==恢复EDI
00401058 5E          pop esi  ==恢复ESI
00401059 5B          pop ebx  ==恢复EBX
0040105A 83 C4 40       add esp,40h  ==恢复ESP
0040105D 3B EC        cmp ebp,esp   ==检查ESP和EBP
0040105F E8 5C 01 00 00    call __chkesp (004011c0) ==比较检查结果,若不相等会抛出异常
00401064 8B E5        mov esp,ebp    ==恢复esp
00401066 5D          pop ebp     ==恢复ebp
00401067 C3          ret

总结:上面汇编指令序列的模式实际是典型的函数调用过程,简单来说就是保存堆栈指针,保存寄存器,根据临时变量的声明,开辟堆栈空间并初始化,压栈传参,调用函数,恢复寄存器,恢复堆栈指针,退出程序。

下一篇,我会在程序中增加更多内容,展示相应的汇编代码底层实现过程。

以上是关于VC++代码的汇编分析的主要内容,如果未能解决你的问题,请参考以下文章

c/c++/vc/汇编 求助一个可以获得硬件ID号啥的方法啊啊

VC++在Win64上不支持内联汇编怎么办啊

VC/C++ 裸属性有啥作用?

VC++代码解释一下

用vc6.0编译出的exe如何提取源代码?

VC++的内联汇编