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的寄存器传递

  • 相关阅读:
    iOS开发时,在Xcode中添加多个Targets进行版本控制
    如何给苹果公司发邮件?
    快快快!27个提升效率的iOS开源库推荐
    史上最全的常用iOS的第三方框架
    Ajax提交与传统表单提交的区别说明
    js原生ajax请求get post笔记
    查看iOS Crash logs
    如何提高iOS开发能力
    iOS 常用的#define合集
    Xcode编译错误和警告汇总
  • 原文地址:https://www.cnblogs.com/wulei0630/p/9446666.html
Copyright © 2011-2022 走看看