1、参考链接
1.1、函数调用原理–参数篇
2、函数需要解决的三大问题:参数、返回值、局部变量
2.1、参数在函数执行前压栈,执行结束后恢复内平栈或外平栈的方式恢复栈顶位置释放空间;
2.2、返回值一般直接存储在寄存器ax中,函数运行结束后在ax中读取
2.3、函数内部的局部变量也是通过栈来存储
3、函数局部变量面临的几个问题
3.1、专用空间,不被其他数据覆盖;
3.2、对栈进行操作,结束后需要对栈进行恢复操作;
3.3、临时空间使用结束后及时释放
4、基本实现思路
4.1、保存栈顶位置(sp);
4.2、将栈顶位置往前移动一段位置做为局部变量专有空间;
4.3、通过原栈顶+偏移位置(bp寄存器)来访问专用的临时空间;
4.4、结束后恢复原来栈顶位置;
4.5、考虑到函数的嵌套调用,保护和恢复bp同样重要!
5.0、汇编代码实现
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 | assume cs:code, ds:data, ss:stack stack segment db 20h dup(1) stack ends data segment db 20h dup(2) data ends code segment start: ;初始化 mov ax, stack mov ss, ax mov sp, 20h mov ax, data mov ds, ax ;业务代码(函数局部变量实现) push 3344h push 4455h call sum;计算结果保存在ax中 add sp, 4 ;退出 mov ah, 4ch int 21h sum: push bp;保护bp mov bp, sp;保护sp sub sp, 10h;空出10个字节给局部变量使用 ;----业务代码------start ;取参数并计算,由于push bp占用了2个字节,参数从bp+4开始 mov ax, [bp+6] add ax, [bp+4] mov [bp-2], 2324h;局部变量1 mov [bp-4], 3435h;局部变量2 ;----业务代码-------end mov sp, bp;恢复sp pop bp;恢复bp ret code ends end start |
6、运行结果:
7、C++源代码反汇编结果
7.1、C++源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // VCTest.cpp : Defines the entry point for the console application. // #include "stdafx.h" int sum(int a, int b) { int c = 20; int d = 30; return a + b; } int main(int argc, char* argv[]) { sum(2, 3); return 0; } |
7.2、函数部分反汇编
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 | 6: int sum(int a, int b) 7: { 0040D7E0 push ebp;保护bp 0040D7E1 mov ebp,esp;保护sp 0040D7E3 sub esp,48h;移动栈顶位置,预留局部变量专用空间 0040D7E6 push ebx 0040D7E7 push esi 0040D7E8 push edi 0040D7E9 lea edi,[ebp-48h] 0040D7EC mov ecx,12h 0040D7F1 mov eax,0CCCCCCCCh 0040D7F6 rep stos dword ptr [edi] 8: int c = 20; 0040D7F8 mov dword ptr [ebp-4],14h;通过bp段偏移地址访问专用空间,跳过bp从bp-4开始 9: int d = 30; 0040D7FF mov dword ptr [ebp-8],1Eh;第二个局部变量递增bp-8 10: return a + b; 0040D806 mov eax,dword ptr [ebp+8] 0040D809 add eax,dword ptr [ebp+0Ch];函数返回值保存在ax寄存器中 11: } 0040D80C pop edi 0040D80D pop esi 0040D80E pop ebx 0040D80F mov esp,ebp;恢复sp 0040D811 pop ebp;恢复bp 0040D812 ret;外平栈 |
8、汇编Demo中实现与Visual C++反汇编得到的结果基本一致!