递归函数分配指针两次?

时间:2014-10-03 18:12:11

标签: c assembly x86

这是一个间接的作业问题,这个问题不在作业上,但我很好奇。 我们有以下功能:

int silly(int n, int *p)
{
    int val, val2;
    if (n > 0)
        val2 = silly(n << 1, &val);
    else
        val = val2 = 0;
    *p = val + val2 + n;
    return val + val2;
}

并告诉它编译成以下汇编代码:

silly:
    pushl %ebp
    movl %esp,%ebp
    subl $20,%esp
    pushl %ebx
    movl 8(%ebp),%ebx
    testl %ebx,%ebx
    jle .L3
    addl $-8,%esp
    leal -4(%ebp),%eax
    pushl %eax
    leal (%ebx,%ebx),%eax
    pushl %eax
    call silly
    jmp .L4
    .p2align 4,,7
.L3:
    xorl %eax,%eax
    movl %eax,-4(%ebp)
.L4:
    movl -4(%ebp),%edx
    addl %eax,%edx
    movl 12(%ebp),%eax
    addl %edx,%ebx
    movl %ebx,(%eax)
    movl -24(%ebp),%ebx
    movl %edx,%eax
    movl %ebp,%esp
    popl %ebp
    ret

我在编译之后注意到在-8(ebp),p似乎也被存储了。现在,p也存储在12(ebp)。为什么是这样?我找不到任何明确的代码映射p到-8(ebp)

编辑:我应该澄清这个问题,我在这里编译了这段代码:https://gist.github.com/jamiees2/dceaf1ba90b84ebbac0egcc -Wall -m32 test2.c test2.s -o bla然后gdb bla。我在愚蠢的b silly设置断点,然后分别运行x/x *((int*)($ebp+12))/x *((int*)($ebp-8)),这给出了相同的输出。我想知道为什么会这样。它只是堆栈上的垃圾吗?或者那里有一些隐藏的功能吗?

1 个答案:

答案 0 :(得分:0)

传入的参数n存储在8(%ebp)。传入的参数p存储在12(%ebp)。你误解了汇编程序代码。

val存储在-4(%ebp)。已保存的%ebx值存储在-24(%ebp)。请注意,%ebx会在调用中保留。这就是为什么silly保存并恢复它的原因,以及为什么它可以依赖%ebxn的递归调用中继续包含silly的值。