Lets look at a recursive factorial function:
int fact (int n) {
if (n == 0)
return 1;
return n * fact(n-1);
}
In assembly, this turns into:
|
|
Assembly code: |
C style assembly: |
fact: |
pushl |
%ebp |
*--sp=bp; |
|
movl |
$1, %eax |
ax=1; |
|
movl |
%esp, %ebp |
bp=sp; |
|
subl |
$8, %esp |
sp=8; |
|
movl |
%ebx,-4(%ebp) |
bp[-1]=bx; |
|
movl |
8(%ebp),%ebx |
bx=bp[2]; |
|
tstl |
%ebx,%ebx |
if (n!=0); |
|
jne |
L5 |
goto L5; |
L1: |
movl |
-4(%ebp),%ebx |
bx=bp[-1]; |
|
movl |
%ebp,%esp |
sp=bp; |
|
popl |
%ebp |
bp=*sp++; |
|
ret |
|
i=*sp++; |
L5: |
leal |
-1(%ebx),%eax |
ax=bx-1; |
|
movl |
%eax,(%esp) |
*sp=ax; |
|
call |
fact |
*sp++=ip; |
|
imull |
%ebx,%eax |
ax*=bx; |
|
jmp |
L1 |
goto L1; |
What can go wrong?
- Hard to change conventions-complete recompilation
- Callee can stomp on caller's storage or caller's caller
- Caller isn't insulated from callee disasters
- Caller can mess up callee
- Callee can loop forever