函数堆栈

来源:互联网 发布:2017淘宝网下载 编辑:程序博客网 时间:2024/05/29 19:20
#include <windows.h>int func002(char *str, int len){    strcpy(str, "hello");        return len;    }int func001(int x, char y, char *z){    char buff[10];    int aa;        func002(z, aa);        return 0x100;}void main_call(){    int a;    char b;    char c[100];        func001(a, b, c);        func002(c, a);}void main(){    main_call();}



对应的反汇编代码:cl /Fac1.asm cat.c

; Listing generated by Microsoft (R) Optimizing Compiler Version 15.00.21022.08 TITLEE:\code\ctoasm\cat.c.686P.XMMinclude listing.inc.modelflatINCLUDELIB LIBCMTINCLUDELIB OLDNAMES_DATASEGMENT$SG76990 DB'hello', 00H_DATAENDSPUBLIC_func002EXTRN_strcpy:PROC; Function compile flags: /Odtp_TEXTSEGMENT_str$ = 8; size = 4_len$ = 12; size = 4_func002 PROC; File e:\code\ctoasm\cat.c; Line 5pushebpmovebp, esp; Line 6pushOFFSET $SG76990moveax, DWORD PTR _str$[ebp]pusheaxcall_strcpyaddesp, 8; Line 8moveax, DWORD PTR _len$[ebp]   //eax才是函数返回值,len实际未赋值; Line 9popebpret0_func002 ENDP_TEXTENDSPUBLIC_func001; Function compile flags: /Odtp_TEXTSEGMENT_aa$ = -4; size = 4_x$ = 8; size = 4  //0的前面压栈了pc和ebp。_y$ = 12; size = 1_z$ = 16; size = 4_func001 PROC; Line 12pushebpmovebp, espsubesp, 20; 00000014H; Line 16moveax, DWORD PTR _aa$[ebp]pusheaxmovecx, DWORD PTR _z$[ebp]pushecxcall_func002addesp, 8; Line 18moveax, 256; 00000100H //返回值; Line 19movesp, ebppopebpret0_func001 ENDP_TEXTENDSPUBLIC__$ArrayPad$PUBLIC_main_callEXTRN___security_cookie:DWORDEXTRN@__security_check_cookie@4:PROC; Function compile flags: /Odtp_TEXTSEGMENT_c$ = -120; size = 100  //字节对齐108,并填充12字节,所以分配的局部变量空间是120B__$ArrayPad$ = -12; size = 4_b$ = -5; size = 1_a$ = -4; size = 4_main_call PROC; Line 22pushebp  // 每一级的ebp指向上一级的esp起始地址。movebp, espsubesp, 120; 00000078Hmoveax, DWORD PTR ___security_cookiexoreax, ebpmovDWORD PTR __$ArrayPad$[ebp], eax   //&*%*&%; Line 27leaeax, DWORD PTR _c$[ebp]  //为什么不都用eax?pusheaxmovzxecx, BYTE PTR _b$[ebp]   //赋值并清零。pushecxmovedx, DWORD PTR _a$[ebp]pushedxcall_func001addesp, 12; 0000000cH // 调用者将压栈参数弹出堆栈。; Line 29moveax, DWORD PTR _a$[ebp]pusheaxleaecx, DWORD PTR _c$[ebp]pushecxcall_func002addesp, 8; Line 30movecx, DWORD PTR __$ArrayPad$[ebp]xorecx, ebpcall@__security_check_cookie@4   // 大概是堆栈检查的调试功能。movesp, ebp  // 前面将esp保存到ebp中,这里恢复esp的取值,相当于丢弃了局部变量空间。popebpret0_main_call ENDP_TEXTENDSPUBLIC_main; Function compile flags: /Odtp_TEXTSEGMENT_mainPROC; Line 33pushebpmovebp, esp; Line 34call_main_call; Line 35xoreax, eax   //eax存放函数返回值popebpret0_mainENDP_TEXTENDSEND

汇编代码的核心是ESP、EBP的设计。

ESP是函数堆栈指针,每次PUSH减4,每次pop加4.

EBP是每个函数的基址指针,表示该函数的“起始堆栈”,可用户函数返回后恢复堆栈,类似盗梦空间的kick处理。