1、参考链接:
1.1 函数调用原理–参数篇
1.2 函数调用原理–局部变量
2、局部变量空间分配后没有初始化,可能会出现异常访问而出现不可预知的错误,因为分配的临时空间必须初始化;
2.1、将每个字节都初始化为CC其中一种安全策略,因为CC在汇编指令中为int 3,即中断指令。
2.2、stosb/stosw指定能将es:di指向的空间写入ax寄存器中的值,并在执行结束后将di自加1字节/2字节
2.3、rep会循环指定后一条指令,循环次数从cx寄存器中取,如果为0则退出循环
3、汇编代码实现
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 | 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 ;----业务代码----start ;(函数局部变量实现) push 3344h push 4455h call sum;计算结果保存在ax中 add sp, 4 ;----业务代码----end ;退出 mov ah, 4ch int 21h sum: ;1、保护寄存器 push bp;保护bp mov bp, sp;保护sp sub sp, 10h;空出10个字节给局部变量使用 ;保护其他寄存器 push bx push si push di ;2、局部变量空间安全初始化 ;stosw:将ax的值拷贝到es:di中,同时di自+2(stosb自+1) ;2.1、初始化内容 mov ax, 0cccch;使用cccc来初始化,因为cc对应的汇编指令为int 3,即中断指令 ;2.2、设置es值 ;将ss的值赋给es mov bx, ss mov es, bx ;2.3、设置di值 ;将di的值设置为bp-10h,回到局部变量空间的最小端(因为di会自加) mov di, bp sub di, 10h ;2.4、循环赋值初始化所有局部变量空间 ;rep 循环执行,cx为循环次数,循环一次自-1 mov cx, 10h;循环次数为局部变量空间的大小(字操作则除2) rep stosb ;----业务代码------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 ;3、恢复函数调用前各数值,释放空间 ;恢复受保护的寄存器 pop di pop si pop bx mov sp, bp;恢复sp pop bp;恢复bp ret code ends end start |
4、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; } |
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 | 6: int sum(int a, int b) 7: { 0040D7E0 push ebp;保护bp 0040D7E1 mov ebp,esp;保护bp 0040D7E3 sub esp,48h;分配局部变量临时空间 0040D7E6 push ebx;保护bx 0040D7E7 push esi;保护si 0040D7E8 push edi;保护di ;循环初始化将局变量为CCCC 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 9: int d = 30; 0040D7FF mov dword ptr [ebp-8],1Eh 10: return a + b; 0040D806 mov eax,dword ptr [ebp+8] 0040D809 add eax,dword ptr [ebp+0Ch];函数返回值保存在ax中 11: } ;恢复受保护的寄存器,与保护时的顺序相反(因为栈) 0040D80C pop edi;恢复di 0040D80D pop esi;恢复si 0040D80E pop ebx;恢复bx 0040D80F mov esp,ebp;恢复sp 0040D811 pop ebp;恢复bp 0040D812 ret;返回 |