汇编和可执行文件
前面我们已经知道,汇编约等于机器码。源代码通过编译器(也是一个软件)进行编译,得到机器码。以后我们统一用汇编代替机器码。
编译
编译器在编译程序的时候,分为Debug版本和Release版本。编译器不会对Debug版本的程序进行优化,而编译器会对Release版本的程序进行优化。下面是在反汇编的情况下对Debug版本和Release版本进行一下比较。
源代码如下所示:
int main()
{
int iCount = 10;
double dStep = 0.123;
return 0;
}
对应的Debug版本汇编代码如下所示:
int main()
{
000F1A50 push ebp
000F1A51 mov ebp,esp
000F1A53 sub esp,0DCh
000F1A59 push ebx
000F1A5A push esi
000F1A5B push edi
000F1A5C lea edi,[ebp-0DCh]
000F1A62 mov ecx,37h
000F1A67 mov eax,0CCCCCCCCh
000F1A6C rep stos dword ptr es:[edi]
int iCount = 10;
000F1A6E mov dword ptr [iCount],0Ah
double dStep = 0.123;
000F1A75 movsd xmm0,mmword ptr [__real@3fbf7ced916872b0 (0F6CB0h)]
000F1A7D movsd mmword ptr [dStep],xmm0
return 0;
000F1A82 xor eax,eax
}
对应的Release版本汇编代码如下所示:
int iCount = 10;
double dStep = 0.123;
return 0;
008B1000 xor eax,eax
}
从上面汇编代码的结果可以看出,Debug版本的汇编代码会将iCount和dStep这两个变量转换成汇编代码,而Release版本的汇编代码就会将iCount和dStep这两个变量省略掉,也就是会对源代码做一些优化。并且Debug版本生成的可执行文件的大小(本程序为35.5KB)相对于Release版本的可执行程序的大小(本程序为9.00KB)也要大很多。所以我们建议在以后调试程序的时候,最好使用Debug版本进行编译,这样编译器就不会帮我们优化源代码。
链接
整个内存可以分为四个区域,分别为:
-
栈区
栈区具有可增长性。VS为每个线程默认分配1024KB大小的栈空间,如果在栈上分配的空间超过1024KB,就会产生栈溢出的错误。
栈空间使用的大小由两个寄存器来决定,分别是栈底指针和栈顶指针,栈空间中的变量在增加时,栈顶指针就会一点一点的向上移动,到最后如果这些变量都已经没有用了,栈顶指针就会指向栈底指针,表示原来的那些变量已经是垃圾数据了。
如果栈空间上存在函数调用过程(栈的回溯功能),那么还会有保存栈底指针的变量,具体的这里就先不做详细说明了。 - 堆区
- 代码区
- 常量区
这样划分的目的是为了我们编写的程序更加安全。这样划分区域后,就可以将代码区和常量区设置为只读属性,从而达到程序中的代码以及用到的一些常量就不会被意外的修改,提高了程序在运行期间的安全性。
汇编代码
汇编指令:
push代表压栈的操作
pop代表出栈的操作
ebp栈底指针寄存器
esp栈顶指针寄存器
eip程序计数器
efl 标志寄存器
下面一般作为通用寄存器:
eax 累加寄存器
edi 源寄存器
esi 基址寄存器
下面是在main函数中只执行一句printf("Hello World!")语句时,ebp和esp的一系列值。
EBP ESP OPRATION
009DFA30 009DF964
009DF960 offset string "Hello World!" (0A06BCCh)
009DF95C 00A02093 call _printf (0A01370h)
009DF958 00A02900 push ebp
009DF958 00A02901 mov ebp,esp
009DF880 00A02903 sub esp,0D8h
009DF87C 00A02909 push ebx
009DF878 00A0290A push esi
009DF874 00A0290B push edi
009DF870 00A0291E call __vcrt_va_start_verify_argument_type<char const * const> (0A011CCh)
009DF874 00A011CC jmp __vcrt_va_start_verify_argument_type<char const * const> (0A02170h)
009DF870 00A0292C push eax
009DF86C 00A0292D push 0
009DF868 00A02932 push ecx
009DF864 00A02935 push 1
009DF860 00A02937 call dword ptr [__imp____acrt_iob_func (0A0A16Ch)]
009DF85C 53A6D362 push ebp
009DF85C 53A6D363 mov ebp,esp
009DF958 009DF860 53A6D36E pop ebp
009DF864 53A6D36F ret
009DF868 00A0293D add esp,4
009DF864 00A02942 call __RTC_CheckEsp (0A01113h)
009DF868
009DF864 00A02947 push eax
009DF860 00A02948 call __vfprintf_l (0A0136Bh)
009DF85C 00A019C0 push ebp
009DF85C 00A019C1 mov ebp,esp
009DF79C 00A019C3 sub esp,0C0h
009DF798 00A019C9 push ebx
009DF794 00A019CA push esi
009DF790 00A019CB push edi
009DF78C 00A019E3 push eax
009DF788 00A019E7 push ecx
009DF784 00A019EB push edx
009DF780 00A019EF push eax
009DF77C 00A019F0 call ___local_stdio_printf_options (0A01339h)
009DF780 00A01339 jmp __local_stdio_printf_options (0A02AB0h)
009DF77C 00A019F8 push ecx
009DF778 00A019FB push edx
009DF774 00A019FC call dword ptr [__imp____stdio_common_vfprintf (0A0A168h)]
009DF770 53A67FF2 push ebp
009DF770 53A67FF3 mov ebp,esp
009DF76C 53A67FF8 push eax
009DF768 53A67FFC push ecx
009DF764 53A68000 push edx
009DF760 53A68004 push eax
009DF75C 53A68008 push ecx
009DF758 53A6800C push edx
009DF754 53A6800D call 53A4CA90
009DF750 53A4CA92 push ebp
009DF750 53A4CA93 mov ebp,esp
009DF72C 53A4CA95 sub esp,24h
009DF728 53A4CB8A push ecx
009DF724 53A4CB8E push edx
009DF720 53A4CB92 push eax
009DF71C 53A4CB96 push ecx
009DF718 53A4CB9A push edx
009DF714 53A4CB9E call 53A20590
009DF710 53A20592 push ebp
009DF710 53A20593 mov ebp,esp
009DF70C 53A20595 push ecx
009DF710 53A205C8 mov esp,ebp
009DF750 009DF714 53A205CA pop ebp
009DF72C ret
009DF728 53A4CBA3 push eax
009DF724 53A4CBA7 push eax
009DF72C 53A4CBAD add esp,8
009DF750 53A4CBB0 mov esp,ebp
009DF770 009DF754 53A4CBB2 pop ebp
009DF758 53A4CBB3 ret
009DF770 53A68012 add esp,18h
009DF85C 009DF774 53A68015 pop ebp
009DF778 53A68016 ret
009DF790 00A01A02 add esp,18h
009DF794 00A01A0C pop edi
009DF798 00A01A0D pop esi
009DF79C 00A01A0E pop ebx
009DF85C 00A01A0F add esp,0C0h
009DF85C 00A01A17 call __RTC_CheckEsp (0A01113h)
009DF958 009DF860 00A01A1E pop ebp
009DF864 00A01A1F ret
009DF874 00A0294D add esp,10h
009DF878 00A0295D pop edi
009DF87C 00A0295E pop esi
009DF880 00A0295F pop ebx
009DF958 00A02960 add esp,0D8h
009DF958 00A02968 call __RTC_CheckEsp (0A01113h)
009DF958 009DF958 00A0296D mov esp,ebp
009DFA30 009DF95C 00A0296F pop ebp
009DF960 00A02970 ret
009DF964 00A02098 add esp,4
009DF968 00A0209D pop edi
009DF96C 00A0209E pop esi
009DF970 00A0209F pop ebx
009DFA30 00A020A0 add esp,0C0h
009DFA44 009DFA34 00A020AF pop ebp
009DFA38 00A020B0 ret
009DFA44 00A0214E add esp,0Ch
009DFA9C 009DFA48 00A02151 pop ebp
009DFA4C 00A02152 ret
009DFA48 00A01FC2 push ecx
00A01FC3 call _exit (0A012CBh)