Chinaunix首页 | 论坛 | 博客
  • 博客访问: 186114
  • 博文数量: 20
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 965
  • 用 户 组: 普通用户
  • 注册时间: 2014-03-18 23:28
文章分类

全部博文(20)

文章存档

2015年(1)

2014年(19)

分类: 嵌入式

2014-05-26 02:01:20

    栈的定义及规则:  
      
        栈从高位到底位顺序来排列数据, 栈顶<=栈底 && 栈顶>=0, 栈顶始终指向最顶端的数据.  
      
        Push(EAX) : TOP--, S[TOP]=EAX;  //先减栈顶, 再进数据  
        Pop(EAX)  : S[TOP]=EAX, TOP++;  //先出数据,再加栈顶  
      
        初始值:  
        EBP=ESP=20  (EBP-ESP=0,0个数据)  
      
        假如有以下栈段(Step0)与函数ST():  
      
        STACK 0-19   //定义栈开始位置0,共20字节  
      
        0         0                       0                         0                         0                            0  
        1         1                       1                         1                         1                            1  
        2         2                       2                         2                         2                            2  
        3         3                       3                         3                         3                            3  
        4         4                       4                         4                         4                            4  
        5         5                       5                         5                         5                            5  
        6         6                       6                         6                         6                            6        z      ->ESP  
        7         7                       7                         7                         7                            7        y  
        8         8                       8                         8                         8                            8        x  
        9         9                       9                         9        s[3]   ->ESP     9        s[3]   ->EBP=ESP    9        s[3]   ->EBP  
        10        10                      10                        10       s[2]             10       s[2]                10       s[2]  
        11        11                      11                        11       s[1]             11       s[1]                11       s[1]  
        12        12                      12                        12       s[0]             12       s[0]                12       s[0]  
        13        13                      13       r[3]   ->ESP     13       r[3]             13       r[3]                13       r[3]  
        14        14                      14       r[2]             14       r[2]             14       r[2]                14       r[2]  
        15        15                      15       r[1]             15       r[1]             15       r[1]                15       r[1]  
        16        16                      16       r[0]             16       r[0]             16       r[0]                16       r[0]  
        17        17       'a' ->ESP      17       'a'              17       'a'              17       'a'                 17       'a'        
        18        18       'b'            18       'b'              18       'b'              18       'b'                 18       'b'        
        19        19       'c'            19       'c'              19       'c'              19       'c'                 19       'c'  
        Step0     step1                   step2                     step3                     step4                        step5              
      
        函数定义  
        function ST (char a, char b, char c)  
        {  
           char x=a;  
           char y=b;  
           char z=c;  
      
           char n=x+y+z;  
        }  
      
    下面让我们来详细描述一下函数调用时,栈是如何使用的:  
      
    1.将参数压栈:  
      
        push 'c'    ESP-- ESP=19 S[19]='c'   
        push 'b'    ESP-- ESP=18 S[18]='b'   
        push 'a'    ESP-- ESP=17 S[17]='a'   
      
        执行后如图:step1  
      
    2.CALL 函数地址  
      
        将下一个指令的地址压栈,作为函数的返回地址char r[4](4字节的地址)  
        push(r[0])     ESP--  ESP=16  S[16]=r[0]  
        push(r[1])     ESP--  ESP=15  S[15]=r[1]  
        push(r[2])     ESP--  ESP=14  S[14]=r[2]  
        push(r[3])     ESP--  ESP=13  S[13]=r[3]  
          
        注意:整形数据压栈的字节顺序是从低字节到高字节压栈,形成的顺序跟内存中的整数顺序相反  
      
        执行后如图:step2  
      
    3.函数体--保护栈底(EBP)  
      
        char s[4]=EBP;   
      
        push(s[0])     ESP--  ESP=12  S[12]=s[0]   
        push(s[1])     ESP--  ESP=11  S[11]=s[1]   
        push(s[2])     ESP--  ESP=10  S[10]=s[2]   
        push(s[3])     ESP--  ESP=9   S[9] =s[3]   
      
        执行后如图:step3  
      
    4.函数体--设置栈底&&保存栈顶(ESP)  
      
        MOV EBP,ESP         //EBP=ESP  
      
        执行后如图:step4  
      
    5.函数体--声明局部变量  
      
        SUB ESP,0x03        //定义3个局部变量 x,y,z 总长度3个字节,ESP=ESP-3=5  
      
        执行后如图:step5  
      
    6.函数体--使用参数与局部变量  
      
        //参数  
        a=[EBP+8];  
        b=[EBP+9];  
        c=[EBP+10];  
      
        //局部变量  
        x=[EBP-1];  
        y=[EBP-2];  
        z=[EBP-3];  
        
    7.函数体--恢复栈顶(ESP)  
      
        MOV ESP,EBP  
      
        8.函数体--恢复栈底(EBP)  
      
        POP EBP  
      
    9.返回调用函数  
      
        RET,相当于下面指令  
      
        POP EDX // EDX=r[4] 让EDX等于返回地址  
        JMP EDX // 跳转到EDX  
        
        此时,EBP=ESP=20,又恢复到函数调用前的栈状态 
阅读(1598) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~