透过汇编学习C语言
1.变量
全局变量和局部变量
全局变量:在声明并编译后,该变量的内存地址和宽度就被确定,如果不重新编译,则在整个程序运行时,该变量的地址就不会被修改,但是,全局变量中的值可以根据修改其对应地址的值而进行修改。(任何程序或函数都可修改他的值)
局部变量:在声明并编译后,程序并不会直接为其分配地址,只有在运行到该局部变量所在的函数被调用时才会被分配地址和宽度,同时当这个函数执行结束后,该局部变量也会被“清空”
实例学习
源码如下:
#include<stdio.h>
int x;
3: void change(int i){
00401020 push ebp
00401021 mov ebp,esp
00401023 sub esp,44h
00401026 push ebx
00401027 push esi
00401028 push edi
00401029 lea edi,[ebp-44h]
0040102C mov ecx,11h
00401031 mov eax,0CCCCCCCCh
00401036 rep stos dword ptr [edi]
4: int y=i;
00401038 mov eax,dword ptr [ebp+8]
0040103B mov dword ptr [ebp-4],eax
5: x=2;
0040103E mov dword ptr [x (00427c48)],2
6: }
00401048 pop edi
00401049 pop esi
0040104A pop ebx
0040104B mov esp,ebp
0040104D pop ebp
0040104E ret
7: int main(){
00401060 push ebp
00401061 mov ebp,esp
00401063 sub esp,40h
00401066 push ebx
00401067 push esi
00401068 push edi
00401069 lea edi,[ebp-40h]
0040106C mov ecx,10h
00401071 mov eax,0CCCCCCCCh
00401076 rep stos dword ptr [edi]
8: change(2);
00401078 push 2
0040107A call @ILT+0(change) (00401005)
0040107F add esp,4
9: printf("%d\n",x);
00401082 mov eax,[x (00427c48)]
00401087 push eax
00401088 push offset string "%d" (0042201c)
0040108D call printf (004010c0)
00401092 add esp,8
10: return 0;
00401095 xor eax,eax
11: }
开始分析程序(主要从局部变量开始分析)
void change(int i){
00401020 push ebp
00401021 mov ebp,esp
00401023 sub esp,44h
00401026 push ebx
00401027 push esi
00401028 push edi
00401029 lea edi,[ebp-44h]
0040102C mov ecx,11h
00401031 mov eax,0CCCCCCCCh
00401036 rep stos dword ptr [edi]
4: int y=i;
00401038 mov eax,dword ptr [ebp+8]
0040103B mov dword ptr [ebp-4],eax
5: x=2;
0040103E mov dword ptr [x (00427c48)],2
6: }
00401048 pop edi
00401049 pop esi
0040104A pop ebx
0040104B mov esp,ebp
0040104D pop ebp
0040104E ret
该程序的堆栈分析图如下:
2.函数嵌套调用
?
|