C语言基础之内存分布

C语言之内存分布简单分析

Wirte by 021. Leave a message if i messed up ! : )

汇编语言入门教程- 阮一峰的网络日志

C源码 | 脑图模拟汇编Win32

  • win32汇编设计上还是有很多不合理,造成了很多资源浪费,比如断点C的填充,在AT&T的汇编上得到了改良
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

//减函数
int sub(int c){
return c-1;
}


// 加函数
int add(int a , int b){
int c = a + b;
//函数嵌入
c = sub(c);
return c;
}


//main函数
int main(int argc, const char * argv[]) {

// insert code here...
int a = 20;
int b = 10;
int c = add(a,b);
//int a = 7;
//putchar(a);
//printf("Hello, World! %d \n",c);
return 0;
}


================================模拟汇编堆栈====================================


初始堆栈:

esp 0x0000 02ff;
ebp 0x0000 0208;
eip 0x0005 0001;

//预留三个参数寄存器

esi ....
edi ....
ebx ....


============================ main start =====================

// 1. 提栈
0x0005 0001 ------------ push ebp; | esp 0x0000 01fb; ebp 0x0000 0208[0x0000 0208];
0x0005 0002 ------------ mov ebp, esp; | esp 0x0000 01fb; ebp 0x0000 01fb[0x0000 01fb];
0x0005 0003 ------------ sub esp, 0x20; | esp 0x0000 01db; ebp 0x0000 01fb[0x0000 01fb];

// 2. 压栈 - 编译环境不一样,编译器优化汇编 可能有一些差异,整体逻辑是不变的,
// 有的环境是直接取寄存器的值,有的直接压值,这里选择压值,
// win32 压在缓冲区外,AT&T 压在缓冲区内: push 0x14 , ebp - 0x04;
0x0005 0004 ------------ push 0x14; | esp 0x0000 01d7; ebp 0x0000 01fb[0x0000 01fb];
0x0005 0005 ------------ push 0x0a; | esp 0x0000 01d3; ebp 0x0000 01fb[0x0000 01fb];

// 3. 函数调用
0x0005 0006 ------------ call 0x0005 000b; | esp 0x0000 01cf[0x0005 0007]; ebp 0x0000 01fb[0x0000 01fb];
// 此时 eax = 29; esp esp 0x0000 01cf; ebp 0x0000 01fb[0x0000 0208]; eax = 29;


// 4.恢复堆栈
0x0005 0007 ------------ mov esp, ebp; | esp 0x0000 01fb; ebp 0x0000 01fb[0x0000 0208];
0x0005 0008 ------------ pop ebp; | esp 0x0000 01ff; ebp 0x0000 01fb[0x0000 0208];

//由于没有选择寄存器传值,压入的两个参数此时不用处理,平栈的方式很多种,这里似乎可以直接平.
//0x0005 0009 ------------ add esp,0x20; | esp 0x0000 01fb; ebp 0x0000 01fb[0x0000 0208];

0x0005 0009 ------------ ret; | esp 0x0000 01ff; ebp 0x0000 0208;

=================================== main end ===============================



// 加函数
============================ add start ===================== esp 0x0000 01cf

0x0005 000b ------------ push ebp - 0x0c ,eax ; | esp esp 0x0000 01cb; ebp 0x0000 01fb[0x0000 0208];
0x0005 000b ------------ mov ebp, esp ;| esp esp 0x0000 01cb; ebp 0x0000 01cb[0x0000 01cb];

// 加
0x0005 000c ------------ mov eax , ebp - 0x08; | esp 0x0000 01cb; ebp 0x0000 01cb[0x0000 01cb];
0x0005 000d ------------ add eax , ebp - 0x04; | esp 0x0000 01cb; eax = 30;

//压参数
0x0005 000e ------------ push ebp - 0x0c , eax; | esp 0x0000 01c7; eax = 30;
0x0005 000f ---- call 0x0005 0013 | esp esp 0x0000 01c3[0x0005 0000]; ebp 0x0000 01cb[0x0000 01cb];


// 恢复堆栈
0x0005 0000 ------------ pop ebp ; | esp esp 0x0000 01c7; ebp 0x0000 01fb[0x0000 0208];
0x0005 0011 ------------ add esp,0x08 ; | esp 0x0000 01cf; ebp 0x0000 01cb[0x0000 01cb];
0x0005 0012 ------------ ret ; | esp 0x0000 01f9; ebp 0x0000 01fb[0x0000 0208];

=================================add end====================================



// 减函数
============================ sub start =====================
// win32汇编并没有使用寄存器传参,此处eax应该使用寄存器,或者EBP寻址;
0x0005 0013 ------------ sub ebp - 0x0c , 0x01; | esp 0x0000 01c3; ebp 0x0000 01fb[0x0000 0208];
0x0005 0014 ------------ mov eax , ebp - 0x0c; | esp 0x0000 01c3; ebp 0x0000 01fb[0x0000 0208];
0x0005 0015 ------------ ret; | esp 0x0000 01c3; ebp 0x0000 01fb[0x0000 0208]; eax = 29;

============================ sub end =====================