这是一个间接的作业问题,这个问题不在作业上,但我很好奇。 我们有以下功能:
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/dceaf1ba90b84ebbac0e与gcc -Wall -m32 test2.c test2.s -o bla
然后gdb bla
。我在愚蠢的b silly
设置断点,然后分别运行x/x *((int*)($ebp+12))
和/x *((int*)($ebp-8))
,这给出了相同的输出。我想知道为什么会这样。它只是堆栈上的垃圾吗?或者那里有一些隐藏的功能吗?
答案 0 :(得分:0)
传入的参数n
存储在8(%ebp)
。传入的参数p
存储在12(%ebp)
。你误解了汇编程序代码。
val
存储在-4(%ebp)
。已保存的%ebx
值存储在-24(%ebp)
。请注意,%ebx
会在调用中保留。这就是为什么silly
保存并恢复它的原因,以及为什么它可以依赖%ebx
在n
的递归调用中继续包含silly
的值。