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 =====================