Plainly and simply, why do we use _stdcall?
Asked Answered
R

1

6

I've come across calling conventions whilst studying states for game making with C++.

In a previous question someone stated that MSDN doesn't explain _stdcall very well - I agree.

What are the primary purposes for calling conventions like _stdcall? Does it matter what order the arguments are placed on the stack? How does it reduce the size of the code in X86 (as someone else stated)?

Razzledazzle answered 1/12, 2012 at 23:1 Comment(4)
If a function has many arguments and many callers, it makes more sense for the callee to clean up the stack in one place rather than each caller in many places.Forsterite
Are you asking about what drove the design of different calling conventions, or why there is need to specify them at all?Glossography
More just why they're actually used, in simple-people talk :P The MSDN was quite complex and appears to have confused quite a few people!Razzledazzle
possible duplicate of What is the meaning and usage of __stdcall?Seth
A
8

The reason for having some calling convention is pretty simple: so that the caller and the callee agree on how things will work. Without it, the caller doesn't know where to put arguments when it's calling a particular function.

As for why Microsoft decided on the specific details of _stdcall, that's largely historical. On MS-DOS, all calls were register based, so all OS calls required assembly language, or strange extensions to most higher-level languages.

When they first did Windows, they used the cdecl calling convention, mostly because that's what the compiler did by default. At least according to rumor, shortly before they got ready to release Windows 1.0, they switched to the Pascal calling convention because it was enough more efficient that (among other things) it allowed Windows to fit on one fewer floppy disc. Regardless of the precise details, the Pascal calling convention did make code a little smaller, because the called function cleaned up the arguments from the stack instead of needing to clean them up everywhere the function was called. For any function that was called from at least 2 different places, that's a win (and if it's tie anywhere else).

Then they started work on OS/2, and invented yet another calling convention (syscall).

Then, of course, came Win32. There wasn't really a lot wrong with syscall from a technical viewpoint, but (I'd guess) everything associated with OS/2 was considered tainted, so syscall had to go. The result was something just enough different to justify a new name. In fairness, that's a little bit of an exaggeration: they did add one truly useful addition: they encoded the number of bytes of arguments into each function name, so if (for example) you supplied an incorrect prototype for a function, the code wouldn't link rather than ending up with a mismatch between caller and callee that could lead to much more serious problems.

For the most part, it really comes back to the original point though: the exact details of the calling convention don't matter all that much, as long as you don't make a complete mess of it. Most of what matters is that the caller and callee agree on the same thing, so if a compiler knows what parameters a function accepts, it knows how to generate code to get those parameters to the function correctly (and, likewise, they both agree on how stack cleanup is handled, etc.)

Anent answered 1/12, 2012 at 23:31 Comment(6)
Ahh, well that explains why 5 even exist in the first place; I'd have thought they'd keep the one that appears to be the most efficient and updated and scrap the rest! Cheers. That still doesn't quite explain why we need to use one at all though? Is it purely because different compilers use different default calling conventions, so by specifying one we utilise a uniform call method across all compilers/OS's? If so, is it a good practice for me to use them? Or should I not worry about them during my education?Razzledazzle
Calling conventions are one of the things compiler writers debate so they don't get bored :) It is a low level detail you can safely ignore for a long time.Salomesalomi
also, some calling conventions help provide additional "features" that other calling conventions cannot or find harder to provide. For instance, cdecl places the stack cleanup on the caller instead of the callee. This more easily facilitates variable length arguments since only the caller knows how big the stack will be. The caller in this case is the only one who knows how to clean up the stack and is also responsible for this. For stdcall, the only way this could work is if the caller notified the callee of how big the stack will be, but I've not seen this implemented in this way.Fulford
"I'd have thought they'd keep the one that appears to be the most efficient and updated and scrap the rest!" There is often more than one right way to do something.Messere
Just a follow up question, when you say "clean up" after the function return, what does it actually mean?Febrifuge
@Chopnut: Mostly restoring the stack pointer to where it started, so the return address is at the top of the stack (so when it returns, it goes to the right place).Anent

© 2022 - 2024 — McMap. All rights reserved.