栈,函数,参数,局部变量之间的关系

本文详细解析了栈在函数调用过程中的作用,包括参数传递、局部变量声明、栈底保护等关键步骤,并通过具体实例说明了栈顶与栈底指针的变化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文:http://blog.youkuaiyun.com/tdgx2004/article/details/5985531


栈,函数,参数,局部变量之间的关系

分类: VC++ 内联汇编   207人阅读  评论(0)  收藏  举报

[cpp]  view plain copy
  1. 栈的定义及规则:  
  2.   
  3.     栈从高位到底位顺序来排列数据, 栈顶<=栈底 && 栈顶>=0, 栈顶始终指向最顶端的数据.  
  4.   
  5.     Push(EAX) : TOP--, S[TOP]=EAX;  //先减栈顶, 再进数据  
  6.     Pop(EAX)  : S[TOP]=EAX, TOP++;  //先出数据,再加栈顶  
  7.   
  8.     初始值:  
  9.     EBP=ESP=20  (EBP-ESP=0,0个数据)  
  10.   
  11.     假如有以下栈段(Step0)与函数ST():  
  12.   
  13.     STACK 0-19   //定义栈开始位置0,共20字节  
  14.   
  15.     0         0                       0                         0                         0                            0  
  16.     1         1                       1                         1                         1                            1  
  17.     2         2                       2                         2                         2                            2  
  18.     3         3                       3                         3                         3                            3  
  19.     4         4                       4                         4                         4                            4  
  20.     5         5                       5                         5                         5                            5  
  21.     6         6                       6                         6                         6                            6        z      ->ESP  
  22.     7         7                       7                         7                         7                            7        y  
  23.     8         8                       8                         8                         8                            8        x  
  24.     9         9                       9                         9        s[3]   ->ESP     9        s[3]   ->EBP=ESP    9        s[3]   ->EBP  
  25.     10        10                      10                        10       s[2]             10       s[2]                10       s[2]  
  26.     11        11                      11                        11       s[1]             11       s[1]                11       s[1]  
  27.     12        12                      12                        12       s[0]             12       s[0]                12       s[0]  
  28.     13        13                      13       r[3]   ->ESP     13       r[3]             13       r[3]                13       r[3]  
  29.     14        14                      14       r[2]             14       r[2]             14       r[2]                14       r[2]  
  30.     15        15                      15       r[1]             15       r[1]             15       r[1]                15       r[1]  
  31.     16        16                      16       r[0]             16       r[0]             16       r[0]                16       r[0]  
  32.     17        17       'a' ->ESP      17       'a'              17       'a'              17       'a'                 17       'a'        
  33.     18        18       'b'            18       'b'              18       'b'              18       'b'                 18       'b'        
  34.     19        19       'c'            19       'c'              19       'c'              19       'c'                 19       'c'  
  35.     Step0     step1                   step2                     step3                     step4                        step5              
  36.   
  37.     函数定义  
  38.     function ST (char a, char b, char c)  
  39.     {  
  40.        char x=a;  
  41.        char y=b;  
  42.        char z=c;  
  43.   
  44.        char n=x+y+z;  
  45.     }  
  46.   
  47. 下面让我们来详细描述一下函数调用时,栈是如何使用的:  
  48.   
  49. 1.将参数压栈:  
  50.   
  51.     push 'c'    ESP-- ESP=19 S[19]='c'   
  52.     push 'b'    ESP-- ESP=18 S[18]='b'   
  53.     push 'a'    ESP-- ESP=17 S[17]='a'   
  54.   
  55.     执行后如图:step1  
  56.   
  57. 2.CALL 函数地址  
  58.   
  59.     将下一个指令的地址压栈,作为函数的返回地址char r[4](4字节的地址)  
  60.     push(r[0])     ESP--  ESP=16  S[16]=r[0]  
  61.     push(r[1])     ESP--  ESP=15  S[15]=r[1]  
  62.     push(r[2])     ESP--  ESP=14  S[14]=r[2]  
  63.     push(r[3])     ESP--  ESP=13  S[13]=r[3]  
  64.       
  65.     注意:整形数据压栈的字节顺序是从低字节到高字节压栈,形成的顺序跟内存中的整数顺序相反  
  66.   
  67.     执行后如图:step2  
  68.   
  69. 3.函数体--保护栈底(EBP)  
  70.   
  71.     char s[4]=EBP;   
  72.   
  73.     push(s[0])     ESP--  ESP=12  S[12]=s[0]   
  74.     push(s[1])     ESP--  ESP=11  S[11]=s[1]   
  75.     push(s[2])     ESP--  ESP=10  S[10]=s[2]   
  76.     push(s[3])     ESP--  ESP=9   S[9] =s[3]   
  77.   
  78.     执行后如图:step3  
  79.   
  80. 4.函数体--设置栈底&&保存栈顶(ESP)  
  81.   
  82.     MOV EBP,ESP         //EBP=ESP  
  83.   
  84.     执行后如图:step4  
  85.   
  86. 5.函数体--声明局部变量  
  87.   
  88.     SUB ESP,0x03        //定义3个局部变量 x,y,z 总长度3个字节,ESP=ESP-3=5  
  89.   
  90.     执行后如图:step5  
  91.   
  92. 6.函数体--使用参数与局部变量  
  93.   
  94.     //参数  
  95.     a=[EBP+8];  
  96.     b=[EBP+9];  
  97.     c=[EBP+10];  
  98.   
  99.     //局部变量  
  100.     x=[EBP-1];  
  101.     y=[EBP-2];  
  102.     z=[EBP-3];  
  103.     
  104. 7.函数体--恢复栈顶(ESP)  
  105.   
  106.     MOV ESP,EBP  
  107.   
  108.     8.函数体--恢复栈底(EBP)  
  109.   
  110.     POP EBP  
  111.   
  112. 9.返回调用函数  
  113.   
  114.     RET,相当于下面指令  
  115.   
  116.     POP EDX // EDX=r[4] 让EDX等于返回地址  
  117.     JMP EDX // 跳转到EDX  
  118.     
  119.     此时,EBP=ESP=20,又恢复到函数调用前的栈状态  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值