C++程序的编译的时候会把C++代码翻译为汇编代码,然后再把汇编代码转换为obj文件,也就是obj文件里描述了汇编代码的逻辑,我们可以通过工具来把obj文件转换为汇编代码,objconv就是其中一种工具。
objconv用法
下载:https://github.com/gitGNU/objconv
下载后解压。
压缩包里已经有可以直接使用的exe了,找一个任意的obj文件,复制到objconv目录下,进入命令行,执行以下命令。(我用的obj文件是main.obj)
.\objconv-debug.exe -fyasm .\main.obj main.asm
执行成功之后,会生成一个main.asm文件,打开文件就能看到汇编代码了。
总结
结合以上例子的代码来分析。
sub rsp, 24 //rsp表示栈顶指针,-24是压栈
mov dword [rsp+4H], 10 //在栈顶往后偏移4个字节处填入10,定义变量a
mov dword [rsp], 15 //在栈顶位置填入15,定义变量b
mov eax, dword [rsp] //把变量b的值放入寄存器eax
mov ecx, dword [rsp+4H] //把变量a的值放入寄存器ecx
add ecx, eax //两个寄存器相加
mov eax, ecx //把结果放到eax,eax寄存器用作存放函数的返回值
add rsp, 24 //出栈
ret
汇编代码与C++的逻辑相符。
分析以上例子可以看到以下几点。
1、进入一个函数时,rsp指针会往前偏移一定的长度,定义的局部变量会存放在这个区间内,函数退出时,rsp会恢复原位,所以函数中的局部变量会在函数结束时被释放。
2、如果函数的调用栈过多,rsp会一直减,而rsp是有限的,减到一定值就不能再减下去了,这也是函数栈溢出的原理。
3、创建变量时,new出来的变量被放在堆,而被直接创建的变量是存在栈,这里的栈应该就是rsp指针所在的栈。
使用反汇编可以直接看到C++程序的实现过程,对了解原理有一定的帮助。