计算机内存或文件系统中的文件都只不过是一维二进制数组及其对应的二进制地址。所以在计算机的世界里没有乱码,乱码是人类世界的概念。
栈中的变量通常包括:
- 函数参数
- 函数体内声明的局部变量(或叫临时变量)
- 返回值保存在寄存器(eax)中
栈中的变量(参数、局部变量)退出其作用域时,没有一个动作、一段逻辑或代码去释放栈中变量占据的内存,仅仅是没人再去例会当前栈顶上方的若干遗留(历史数据、垃圾值)下来可被后续压栈操作覆盖的无用数据而已。(所以,函数调用结束,释放堆栈的说法是不准确的,仅仅是移动栈顶指针,包括磁盘上删除文件,是释放内存吗,也不是,仅仅是其占据的内存重新标识为可写而已)。
vs 环境的配置
新建 win32 应用程序的空项目完成之后,需要作如下设置,以使 vs 这个 ide 不为我们做更多额外的动作,我们才可看到最原汁原味的 C 语言对应的反汇编代码:
- (0)Debug 而非 Release 模式
- (1)项目 ⇒ 属性 ⇒ 配置属性 ⇒ C/C++ ⇒ 预编译头 、预编译头:不使用预编译头
- (2)项目 ⇒ 属性 ⇒ 配置属性 ⇒ C/C++ ⇒ 代码生成、基本运行时检查:默认值
- (3)项目 ⇒ 属性 ⇒ 配置属性 ⇒ 链接器 ⇒ 高级 ⇒ 随机基址:否
编写如下代码:
int gv = 3;
int func1(int p1, int p2){
return p1 + p2;
}
int main(){
int lv = 4;
gv = func1(lv, 2);
return 0;
}
进入汇编代码阅读环境
以下快捷键(vs2013)会随着 vs 版本的不同而有所区别。
- (1)F11:进入调试环境,以及执行单步的动作
- (2)Ctrl + Alt + D:debug,反汇编窗口
- (3)Ctrl + Alt + G:寄存器窗口
- (4)Ctrl + Alt + M +1/2:分别为内存 1 窗口,和内存 2 窗口
这些都可在调试状态(按下 F11)下,菜单栏 ⇒ 调试 ⇒ 内存(寄存器、反汇编)等看到。
一些简单的结论
当单步到:
int lv = 4;
00411289 C7 45 FC 04 00 00 00 mov dword ptr [lv],4
会看到常量 4 其实占据着从 0041128C 开始的四字节的内存,并非谣传的常量不占内存。