美文网首页
从内存四区来看程序执行过程

从内存四区来看程序执行过程

作者: xiaoliang1 | 来源:发表于2017-12-17 02:43 被阅读44次

    我们都知道一个程序四区:代码区,静态区,栈区,堆区。
    先说一下各个变量以及对象字函数在内存中的的位置:


    02A18AC2-4594-4F0B-B9DD-579A5418F7F1.png

    对象可在栈区,也可在堆区。主要是是不是用malloc ,relloc,calloc,new,alloc等,而这些代码会在代码区存放。静态字符串,全变量等则在静态区。
    为了更好的说明,我们简化一下代码:

    void test(int a);
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // insert code here...
            test(10);//函数地址堆
            //汇编的下局代码地址  栈
        }
        return 0;
    }
    
    void test(int a)
    {
        int pp = 10;
        printf("%d",a + pp);
    }
    

    然后打个断点看看。


    DC1FAF09-1199-4E1E-85FB-924BD6BFAED6.png

    test 函数的函数地址是0x100000f30;而返回地址应该是0x100000f19;
    而作为参数( movl $0xa, %edi)的10应该是栈区的,我刚刚重新运行了代码,所以地址有所偏差,我去看看栈区。
    那么怎么看栈区,先用 register read看看堆栈的区域

    C608071C-5338-4CA8-BD9C-5AB39F919357.png

    (可以看出代码段指针是rip.)
    我们注意到rbp和rsp 分别是0x00007fff5fbff660。和0x00007fff5fbff640。这一块就是当前的栈区了。我在我去读下memory read --size 8 -f x --count 20 0x00007fff5fbff640


    94603A1C-A4DA-4091-B192-4EA9A5E597FC.png

    发现没有10 没入栈,这是为什么呢。以为上面的汇编地址:

    ->  0x100000f10 <+32>: movq   %rax, -0x18(%rbp)
    

    说明这样传值进去平不会把10放进栈区。那加一个变量吧。立马会有的最终代码是这样的:

    void test(int a);
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // insert code here...
    
            int a = 10;
            test(a);//函数地址堆
            //汇编的下局代码地址  栈
        }
        return 0;
    }
    
    void test(int a)
    {
        int pp = 10;
        printf("%d",a + pp);
    }
    

    汇编代码如下:


    EBBDDAF2-CD65-4237-902D-A2AFBDFCA29B.png
    0x100000f0b <+27>: movl   $0xa, -0x14(%rbp)
    

    10被放在rbp-0x14的地方了。由于加了一句代码返回地址变为:0x0000000100000f1e(执行完test函数要到test下面代码这里执行。)。


    ED72CE3A-7957-4091-B08E-01765273207C.png

    int 占4个自己所以size 要用4了。可以清楚的看到int a 被放进栈区了。
    其实test 函数地址也是在栈区的。上面有说过返回地址(call 0x10000f1e)也是在栈区的。虽然没有看到把函数地址和返回地址入栈。说明call方法帮我做了这些。我在test方法里面打了断点。进去看看。看看栈内存就知道了。


    5A2CC5BD-0F27-4B6F-9C4C-D5F099C04B78.png
    确实返回函数已经入栈。
    在返回地址上面我可以看出里面有个10也入栈了(--szie 4看的话)。

    这充分说明实参和形参是值传递。我就截图给你们看看吧:


    FC704615-011C-4A3A-9FD8-8E80E3B91AE4.png

    地址明显不一样哦。
    还有可以看看当前栈区地址。和main里面又啥不一样。
    此外可以看看返回值是问题。我可以告诉你返回值是rax寄存器里面的。

    相关文章

      网友评论

          本文标题:从内存四区来看程序执行过程

          本文链接:https://www.haomeiwen.com/subject/mpmdwxtx.html