Before answering your questions. Instead of commenting on what the code does, I comment on where all the values ββare in the register or on the stack.
The arguments are on the stack, the return value is in %eax .
The registers %eax , %ecx and %edx are preserved. All other registers, including %ebx , %ebp and %esp , are stored in memory ( %edi and %esi not used).
My stack designation is 4 bytes at a time, and I use ; for those ebp points, if known.
silly: ; eax: ?, ebx: ebx0, edx: ?, stack: [eip0, n, p] pushl %ebp ; eax: ?, ebx: ebx0, edx: ?, stack: [ebp0, eip0, n, p] movl %esp,%ebp ; eax: ?, ebx: ebx0, edx: ?, stack: [; ebp0, eip0, n, p] subl $20,%esp ; eax: ?, ebx: ebx0, edx: ?, stack: [?, ?, ?, ?, ?; ebp0, eip0, n, p] pushl %ebx ; eax: ?, ebx: ebx0, edx: ?, stack: [ebx0, ?, ?, ?, ?, ?; ebp0, eip0, n, p] movl 8(%ebp),%ebx ; eax: ?, ebx: n, edx: ?, stack: [ebx0, ?, ?, ?, ?, ?; ebp0, eip0, n, p] testl %ebx,%ebx ; set flags from n jle .L3 ; if flags indicates <= 0, goto .L3, else fallthrough ; set up for calling the function addl $-8,%esp ; eax: ?, ebx: n, edx: ?, stack: [?, ?, ebx0, ?, ?, ?, ?, ?; ebp0, eip0, n, p] leal -4(%ebp),%eax ; eax: &val, ebx: n, edx: ?, stack: [?, ?, ebx0, ?, ?, ?, ?, (stackeax); ebp0, eip0, n, p] pushl %eax ; eax: &val, ebx: n, edx: ?, stack: [&val, ?, ?, ebx0, ?, ?, ?, ?, val=?; ebp0, eip0, n, p] leal (%ebx,%ebx),%eax ; eax: 2*n, ebx: n, edx: ?, stack: [&val, ?, ?, ebx0, ?, ?, ?, ?, val=?; ebp0, eip0, n, p] pushl %eax ; eax: 2*n, ebx: n, edx: ?, stack: [2*n, &val, ?, ?, ebx0, ?, ?, ?, ?, val=?; ebp0, eip0, n, p] call silly ; pushes eip; args: (2*n, &val); val will be initialized on return jmp .L4 ; ; .p2align 4,,7 ; request alignment (there should be one before `silly:` too) .L3: ; xorl %eax,%eax ; eax: val=0, ebx: n, edx: ?, stack: [ebx0, ?, ?, ?, ?, ?; ebp0, eip0, n, p] movl %eax,-4(%ebp) ; eax: val=0, ebx: n, edx: ?, stack: [ebx0, ?, ?, ?, ?, val; ebp0, eip0, n, p] ; .L4: ; eax: val2=Ο(function result, 0), ebx: n, edx: ?, stack: [..., ebx0, ?, ?, ?, ?, val; ebp0, eip0, n, p] movl -4(%ebp),%edx ; eax: val2, ebx: n, edx: val, stack: [..., ebx0, ?, ?, ?, ?, val; ebp0, eip0, n, p] addl %eax,%edx ; eax: val2, ebx: n, edx: val+val2, stack: [..., ebx0, ?, ?, ?, ?, val; ebp0, eip0, n, p] movl 12(%ebp),%eax ; eax: p, ebx: n, edx: val+val2, stack: [..., ebx0, ?, ?, ?, ?, val; ebp0, eip0, n, p] addl %edx,%ebx ; eax: p, ebx: n+val+val2, edx: val+val2, stack: [..., ebx0, ?, ?, ?, ?, val; ebp0, eip0, n, p] movl %ebx,(%eax) ; *p = n+val+val2 movl -24(%ebp),%ebx ; eax: p, ebx: ebx0, edx: val+val2, stack: [..., ebx0, ?, ?, ?, ?, val; ebp0, eip0, n, p] movl %edx,%eax ; eax: val+val2, ebx: ebx0, edx: val+val2, stack: [..., ebx0, ?, ?, ?, ?, val; ebp0, eip0, n, p] movl %ebp,%esp ; eax: val+val2, ebx: ebx0, edx: val+val2, stack: [; ebp0, eip0, n, p] popl %ebp ; eax: val+val2, ebx: ebx0, edx: val+val2, stack: [eip0, n, p] ret ; eax: val+val2, ebx: ebx0, edx: val+val2, stack: [n, p]
STOP .
Go back and re-read the code again. You only harm yourself if you yourself do not figure out the answers. It should be easy with the comments I wrote.
But anyway...
- but.
val usually on the stack, << 212>. The only time this is not the case on the xorl %eax,%eax line xorl %eax,%eax
b. it is stored at -4(%ebp) , as evidenced by the lines leal -4(%ebp),%eax , movl %eax,-4(%ebp) and movl -4(%ebp),%edx . In addition, the previous val frame is *p
from. val must be on the stack so that its address can be taken and passed to a recursive call. - but.
val2 never stored on the stack, although most likely some of them ? are spaces reserved for it.
b. it is stored in regixter eax at .L4 , which in the first branch of the phi function is the return value of the recursive call, and on the second branch, the value 0 , which was also stored in val >.
from. val2 should never be on the stack, since its address is not executed, it does not exist until the recursive call, so it does not need to be saved, and there are quite a few registers that need not be spilled. - but.
-24(%ebp) is the saved value of %ebx , from the pushl %ebx
b. %ebx is a register stored in the request, so its value must be saved. - but. No, there is nothing there.
b. Most likely, it would be val2 if it were necessary to shed. My best guess is that the other three ? reserved for registers stored unsupported as recursive calls: %eax , %ecx and %edx .