过程堆栈布局 [英] stack layout for process

查看:192
本文介绍了过程堆栈布局的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么是输出44而不是12,和放大器; X,EIP,EBP,和放大器; j可以为code堆栈布局
下面给出我想,如果是的话,那么它必须有12个作为输出,但我得到它44?
所以帮助我理解这个概念,altough基指针被重新定位为执行的每一个瞬间,相对必须保持不变,而不是它应该是12?

  INT的main(){
    INT X = 9;
    //的printf(%P为x \\ n的地址,&安培; X);
    有趣(安培; X);
    的printf(%X为x \\ n的地址(安培; X));
    X = 3;
    的printf(%d个x被的\\ n,x)的;
    返回0;
}INT乐趣(无符号整数* PTR){
    诠释J;
    的printf(差别%U \\ N((无符号整数)PTR - (无符号整数)及j)条);
    的printf(j的地址是%X \\ n,&安培; j)条;    返回0;
}


解决方案

没有,应该的的是12.应当的的是任何东西。 ISO标准已经很少说的事情是如何安排在堆栈上。一个实现在各地移动的东西和效率插入填充的回旋余地很大。

如果您有一个选项来生成自己的汇编code通过它通过你的编译器(如用 GCC -S ),它将成为以什么明显发生在这里。

 乐趣:
    pushl%EBP
    MOVL%ESP,EBP%
    subl $ 40%ESP ;;这是相当大的(见下文)。
    MOVL 8(EBP%),EDX%
    莱亚尔-12(%EBP),EAX%
    MOVL%EDX,ECX%
    subl%EAX,ECX%
    MOVL%ECX,EAX%
    MOVL%EAX,4(%ESP)
    MOVL $ .LC2(%ESP)
    调用printf
    莱亚尔-12(%EBP),EAX%
    MOVL%EAX,4(%ESP)
    MOVL $ .LC3(%ESP)
    调用printf
    MOVL $ 0,%EAX
    离开
    RET

看来, GCC 是pre-产生下一​​个堆栈帧(一个下到的printf )作为序言的乐趣功能的一部分。这就是在这种情况下。你的编译器可能会做完全不同的东西。但底线是:实现可以做它喜欢的,只要它不违反标准

这是从优化级别0 code,顺便说一下,它给出了48的差异。当我使用gcc的疯狂优化级别3,我得到4的差别同样,完全可以接受的,GCC通常不会一些pretty IM pressive优化技术在这一水平。

why is the output 44 instead of 12, &x,eip,ebp,&j should be the stack layout for the code given below i guess, if so then it must have 12 as output, but i am getting it 44? so help me understand the concept,altough the base pointer is relocated for every instant of execution, the relative must remain unchanged and should not it be 12?

int main() {
    int x = 9;
    // printf("%p is the address of x\n",&x);
    fun(&x );
    printf("%x is the address of x\n", (&x));
    x = 3;
    printf("%d x is \n",x);
    return 0;
}

int fun(unsigned int *ptr) {    
    int j;
    printf("the difference is  %u\n",((unsigned int)ptr -(unsigned int) &j));
    printf("the address of j is %x\n",&j);

    return 0;
}

解决方案

No, it should not be 12. It should not be anything. The ISO standard has very little to say about how things are arranged on the stack. An implementation has a great deal of leeway in moving things around and inserting padding for efficiency.

If you pass it through your compiler with an option to generate he assembler code (such as with gcc -S), it will become evident as to what's happening here.

fun:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $40, %esp            ;; this is quite large (see below).
    movl    8(%ebp), %edx
    leal    -12(%ebp), %eax
    movl    %edx, %ecx
    subl    %eax, %ecx
    movl    %ecx, %eax
    movl    %eax, 4(%esp)
    movl    $.LC2, (%esp)
    call    printf
    leal    -12(%ebp), %eax
    movl    %eax, 4(%esp)
    movl    $.LC3, (%esp)
    call    printf
    movl    $0, %eax
    leave
    ret

It appears that gcc is pre-generating the next stack frame (the one going down to printf) as part of the prolog for the fun function. That's in this case. Your compiler may be doing something totally different. But the bottom line is: the implementation can do what it likes as long as it doesn't violate the standard.

That's the code from optimisation level 0, by the way, and it gives a difference of 48. When I use gcc's insane optimisation level 3, I get a difference of 4. Again, perfectly acceptable, gcc usually does some pretty impressive optimisations at that level.

这篇关于过程堆栈布局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆