zoukankan      html  css  js  c++  java
  • 函数调用过程及函数调用栈研究

    函数调用栈为ABI规范的内容,不同的操作系统有不同的约定。

    Arm+Linux平台下函数调用过程的研究

    1. C语言代码:

    int add(int a, int b, int c, int d, int e)
    {    
        int f = 3;
        int g = 4;
        return (a + b + c + d + e + f + g);
    }
    
    int main()
    {    
        int a = 0;
        
        a = add(1, 2, 3, 4, 5);
    
        return 0;
    }

    2. C语言代码反汇编:arm-linux-objdump -D -S Test > dump

    0000834c <add>:
    int add(int a, int b, int c, int d, int e)
    {    
        834c:    e52db004     push    {fp}        ; (str fp, [sp, #-4]!)
        8350:    e28db000     add    fp, sp, #0    ; 0x0
        8354:    e24dd01c     sub    sp, sp, #28    ; 0x1c
        8358:    e50b0010     str    r0, [fp, #-16]
        835c:    e50b1014     str    r1, [fp, #-20]
        8360:    e50b2018     str    r2, [fp, #-24]
        8364:    e50b301c     str    r3, [fp, #-28]
        int f = 3;
        8368:    e3a03003     mov    r3, #3    ; 0x3
        836c:    e50b300c     str    r3, [fp, #-12]
        int g = 4;
        8370:    e3a03004     mov    r3, #4    ; 0x4
        8374:    e50b3008     str    r3, [fp, #-8]
        return (a + b + c + d + e + f + g);
        8378:    e51b2010     ldr    r2, [fp, #-16]
        837c:    e51b3014     ldr    r3, [fp, #-20]
        8380:    e0822003     add    r2, r2, r3
        8384:    e51b3018     ldr    r3, [fp, #-24]
        8388:    e0822003     add    r2, r2, r3
        838c:    e51b301c     ldr    r3, [fp, #-28]
        8390:    e0822003     add    r2, r2, r3
        8394:    e59b3004     ldr    r3, [fp, #4]
        8398:    e0822003     add    r2, r2, r3
        839c:    e51b300c     ldr    r3, [fp, #-12]
        83a0:    e0822003     add    r2, r2, r3
        83a4:    e51b3008     ldr    r3, [fp, #-8]
        83a8:    e0823003     add    r3, r2, r3
    }
        83ac:    e1a00003     mov    r0, r3
        83b0:    e28bd000     add    sp, fp, #0    ; 0x0
        83b4:    e8bd0800     pop    {fp}
        83b8:    e12fff1e     bx    lr
    
    000083bc <main>:
    
    int main()
    {    
        83bc:    e92d4800     push    {fp, lr}
        83c0:    e28db004     add    fp, sp, #4    ; 0x4
        83c4:    e24dd010     sub    sp, sp, #16    ; 0x10
        int a = 0;
        83c8:    e3a03000     mov    r3, #0    ; 0x0
        83cc:    e50b3008     str    r3, [fp, #-8]
        
        a = add(1, 2, 3, 4, 5);
        83d0:    e3a03005     mov    r3, #5    ; 0x5
        83d4:    e58d3000     str    r3, [sp]
        83d8:    e3a00001     mov    r0, #1    ; 0x1
        83dc:    e3a01002     mov    r1, #2    ; 0x2
        83e0:    e3a02003     mov    r2, #3    ; 0x3
        83e4:    e3a03004     mov    r3, #4    ; 0x4
        83e8:    ebffffd7     bl    834c <add>
        83ec:    e1a03000     mov    r3, r0
        83f0:    e50b3008     str    r3, [fp, #-8]
    
        return 0;
        83f4:    e3a03000     mov    r3, #0    ; 0x0
    }


     

    3. 函数调用及返回过程,fp指针(当前函数栈针基地址)和sp指针(指向栈顶的指针)的变化

    (1) 前四个参数由寄存器R0~R3传递,多于四个的参数用栈传递

    (2) 函数调用调用函数动作:

    ① 将多于四个的参数压入栈,以sp指针作为基地址

    ② 将前四个参数写入寄存器R0~R3

    ③ 跳转到被调用函数地址

    (3) 函数调用被调用函数动作,

    ① 将fp压入栈,且sp - 4 (这个fp为调用函数的栈帧基地址)

    ② 将sp赋值给fp,然后sp减去一个数(这一步是给被调用函数分配栈帧,减去的数值即为栈帧大小)

    ③ 在新的栈帧上为参数(保存于R3~R0)分配空间,为局部变量分配空间

    ④ 返回:返回值由R0传递,然后将fp赋值给sp,且弹出保存于栈中的调用函数栈针基地址fp

    X86+Linux平台与Arm+Linux平台有类似的函数调用过程

    1. C语言源代码

    #include <stdio.h>
    
    int add(int a, int b, int c, int d, int e)
    {    
        int f = 6;
        int g = 7;
        
        return (a + b + c + d + e + f + g);
    }
    
    int main()
    {    
        int a = 0;
        
        a = add(1, 2, 3, 4, 5);
    
        return 0;
    }

    2. C语言代码反汇编: objdump -D -S Test > dump

    int add(int a, int b, int c, int d, int e)
    {    
     8048394:    55                       push   %ebp
     8048395:    89 e5                    mov    %esp,%ebp
     8048397:    83 ec 10                 sub    $0x10,%esp
        int f = 6;
     804839a:    c7 45 f8 06 00 00 00     movl   $0x6,-0x8(%ebp)
        int g = 7;
     80483a1:    c7 45 fc 07 00 00 00     movl   $0x7,-0x4(%ebp)
        
        return (a + b + c + d + e + f + g);
     80483a8:    8b 45 0c                 mov    0xc(%ebp),%eax
     80483ab:    8b 55 08                 mov    0x8(%ebp),%edx
     80483ae:    8d 04 02                 lea    (%edx,%eax,1),%eax
     80483b1:    03 45 10                 add    0x10(%ebp),%eax
     80483b4:    03 45 14                 add    0x14(%ebp),%eax
     80483b7:    03 45 18                 add    0x18(%ebp),%eax
     80483ba:    03 45 f8                 add    -0x8(%ebp),%eax
     80483bd:    03 45 fc                 add    -0x4(%ebp),%eax
    }
     80483c0:    c9                       leave  
     80483c1:    c3                       ret    
    
    080483c2 <main>:
    
    int main()
    {    
     80483c2:    55                       push   %ebp
     80483c3:    89 e5                    mov    %esp,%ebp
     80483c5:    83 ec 24                 sub    $0x24,%esp
        int a = 0;
     80483c8:    c7 45 fc 00 00 00 00     movl   $0x0,-0x4(%ebp)
        
        a = add(1, 2, 3, 4, 5);
     80483cf:    c7 44 24 10 05 00 00     movl   $0x5,0x10(%esp)
     80483d6:    00 
     80483d7:    c7 44 24 0c 04 00 00     movl   $0x4,0xc(%esp)
     80483de:    00 
     80483df:    c7 44 24 08 03 00 00     movl   $0x3,0x8(%esp)
     80483e6:    00 
     80483e7:    c7 44 24 04 02 00 00     movl   $0x2,0x4(%esp)
     80483ee:    00 
     80483ef:    c7 04 24 01 00 00 00     movl   $0x1,(%esp)
     80483f6:    e8 99 ff ff ff           call   8048394 <add>
     80483fb:    89 45 fc                 mov    %eax,-0x4(%ebp)
    
        return 0;
     80483fe:    b8 00 00 00 00           mov    $0x0,%eax


    3. 从反汇编代码中可以看出,X86平台和Arm平台函数调用过程类似

    ① X86的esp等价于Arm的sp, X86的ebp等价于Arm的fp

    ② X86的参数传递是直接用栈传递的,并未用CPU的寄存器传递

  • 相关阅读:
    Using Resource File on DotNet
    C++/CLI VS CSharp
    JIT VS NGen
    [Tip: disable vc intellisense]VS2008 VC Intelisense issue
    UVa 10891 Game of Sum(经典博弈区间DP)
    UVa 10723 Cyborg Genes(LCS变种)
    UVa 607 Scheduling Lectures(简单DP)
    UVa 10401 Injured Queen Problem(简单DP)
    UVa 10313 Pay the Price(类似数字分解DP)
    UVa 10635 Prince and Princess(LCS N*logN)
  • 原文地址:https://www.cnblogs.com/wulei0630/p/9446666.html
Copyright © 2011-2022 走看看