In: Computer Science
Consider the following C code:
long fact(long x) { if (x <= 1) {
return 1; }
long px = x; long fx = fact(x - 1); return px * fx;
}
Copy the above C code into a C file. For each line of C code responsible for a push or pop operation (either directly or as a result of a call or return), add a comment describing the stack operation and its purpose.
Hint: try compiling the C code to x86-64 using Arch gcc with the -S, -Og flags.
long fact(long x) { // BEFORE
ENTERING fact: push the value of x onto the stack
// BEFORE ENTERING fact: push the return address
of next statement (from wherever fact is called) on stack
if (x <= 1) {
return 1;
// WHILE RETURNING from fact:
pop local variable px off the stack
// WHILE RETURNING from fact: pop return address
and save this so that jmp can be done to this address
// WHILE RETURNING FROM fact: pop parameter
(value of x) from stack
}
long px = x;
// push local variable px onto the stack
long fx = fact(x - 1); // BEFORE ENTERING fact: push
the value of (x - 1) onto the stack
// BEFORE ENTERING fact: push the return address
of next statement (i.e. return px * fx) on stack
// WHILE RETURNING: pop local variable px off
the stack
// WHILE RETURNING from fact: pop return address
and save this so that jmp can be done to this address
// WHILE RETURNING FROM fact: pop parameter
(value of x - 1) from stack
return px * fx;
// WHILE RETURNING from fact: pop local variable px off the
stack
// WHILE RETURNING from fact: pop return address
and save this so that jmp can be done to this address
// WHILE RETURNING FROM fact: pop parameter
(value of x) from stack
}