My understanding is that, if a void function is executed without a return statement, then %rax will still store whatever is returned from the previous non-void function.
That is, if:
int a(int param){
return param;
}
void b(){
}
int main(){
a(5);
b();
return 1;
}
Then after main finishes execution but before returning, the value stored in %rax will be 5.
My question is, what happens if b has an empty return statement? That is,
void b(){
return;
}
Does that clear out %rax? Or does %rax still retain its previous value still?
then %rax will still store whatever is returned from the previous non-void function.
No, your understanding is wrong.
When RAX doesn't hold a return value (void or FP functions), it's a call-clobbered register like RCX or RSI for example. Read the calling convention docs or look at compiler output.
And BTW, an explicit return
statement vs. reaching the }
at the bottom is completely irrelevant. (Except that falling off the end of a non-void
function is UB, and some compilers will compile that to a ud2
illegal instruction.)
Then after main finishes execution but before returning, the value stored in %rax will be 5.
That is 100% implementation detail; a compiler can do anything it wants with registers within a function, like use RAX to evaluate non-function-call expressions. The calling convention only nails down the boundaries between functions.