Search

Using Win32 Calling Conventions

0 views

When writing code for the Win32 platform, most developers don't pay attention to selecting a "calling convention", and in most cases it doesn't really matter much. But as systems get larger and split into more modules (especially when third-party modules are to be included), this becomes something that cannot really be ignored. In this Tech Tip, we discuss what the MSVC calling conventions are, why to choose one over the other, and "big system" considerations that may not be obvious. Calling Conventions Traditionally, C function calls are made with the caller pushing some parameters onto the stack, calling the function, and then popping the stack to clean up those pushed arguments. /* example of __cdecl */ push arg1 push arg2 push arg3 call function add sp,12 // effectively "pop; pop; pop" It turns out that Microsoft compilers on Windows (and probably most others) support not just this convention, but two others as well. The technical details are found at /* example of __stdcall */ push arg1 push arg2 push arg3 call function // no stack cleanup - callee does this This looks like a minor technical detail, but if there is a disagreement on how the stack is managed between the caller and the callee, the stack will be destroyed in a way that is unlikely to be recovered. A mismatch in calling convention is catastrophic for a running program. At first this seems like a not-that-interesting distinction (to many it is in fact not-that-interesting), but there are several implications that arise when considering one or the other. We'll note that there is also a __fastcall convention that uses registers, but we don't believe it's really that useful in the general case - the save and restore of the registers often removes any speed benefit of using the register for arg passing. We'll only touch on it in passing.

  • Variadic functions like printf() are almost impossible to get right with __stdcall, because only the caller really knows how many arguments were passed in order to clean them up. The callee can make some good guesses (say, by looking at a format string), but the stack cleanup would have to be determined by the actual logic of the function, not the calling-convention mechanism itself. Hence only __cdecl supports variadic functions so that the caller can do the cleanup.

Share this article

Comments (0)

Please sign in to leave a comment.

No comments yet. Be the first to comment!