Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What prevents the callee from cleaning up the stack?

As part of extending my curriculum, I'm slowly descending down the ladder of programming abstraction. Right now I have good command of C, and I'm making preparations for writing some assembly (ARM assembly, specifically).

I've encountered the topic of calling conventions, and while I generally understand their sense, the question that never seems to be asked or answered is:

Why can't the callee handle variable arguments on the stack?

Everywhere it says that the called function doesn't know how many parameters have been passed, but in that case why isn't it possible to simply put that data into a register or push it onto the top of the stack for the called function to use?

I'm asking this question with respect to any architecture that utilises stacks for subroutine communication, not just ARM or x86.

like image 422
Thomas K. Avatar asked Dec 19 '22 21:12

Thomas K.


1 Answers

The callee can clean variable arguments from the stack. I made it once, actually. But the code is pretty big.

Anyway, the main reason why in cdecl convention, the caller cleans the stack is other. (The variable arguments procedures are very few, after all)

On some architectures (usually very small, as the old 8080 or 6800), there is no ret n instruction that to automate the stack cleaning and as a rule they can't make arithmetics with the stack pointer as well.

So, the callee have to first pop the return address from the stack in order to reach the arguments, then to pop all arguments and then push back the return address. For 3 arguments it will look this way with stdcall convention:

    push arg1
    push arg2
    push arg3
    call proc

proc:
    pop  r1   ; the return address
    pop  r2
    pop  r2
    pop  r2
    push r1
    ret

When cdecl convention is used 2 instructions and one register use are spared:

    push arg1
    push arg2
    push arg3
    call proc
    pop  r2
    pop  r2
    pop  r2

proc:
    ret

And because for single language it is better to use single calling convention on all platforms, the CCALL as more simple and universal looks better. (C language is created in times when 6800 was a high tech).

But notice, that on these platforms, the assembly programs and the native languages (for example different kind of BASICs) usually use register argument passing which is of course much more faster on such small systems.

Anyway, it is just a tradition. You can set the compiler to use whatever convention you want. For example, WinAPI is written in C++ but still uses stdcall convention, because it is better on x86 platform.

like image 61
johnfound Avatar answered Jan 06 '23 12:01

johnfound