The stdcall calling convention is almost identical to cdecl in that parameters are passed on to the stack in the same manner--the rightmost is pushed first and leftmost is pushed last. The only difference is that the caller does not have to take care of stack cleanup:
macro stdcall procName, [args]
{
if ~args eq
reverse
push args
end if
common
call procName
}
Let's consider a simple example that uses both the calling conventions:
cdecl_proc:
push ebp
mov ebp, esp
; body of the procedure
mov esp, ebp
pop ebp,
ret
stdcall_proc:
push ebp
mov ebp, esp
; body of the procedure
mov esp, ebp
pop ebp
ret 8 ; Increments the stack pointer by 8 bytes after
; return, thus releasing the space occupied
; by procedure parameters
main:
ccall cdecl_proc, 128 ; 128 is a numeric parameter passed to
; the procedure
stdcall stdcall_proc, 128, 32
While all is clear with the cdecl_proc and stdcall_proc procedures, let's take a closer look at what the main procedure expands to:
main:
push 128
call cdecl_proc
add esp, 4
;
push 32
push 128
call stdcall_proc
In the preceding example, the stdcall macro invocation also illustrates what happens when there is more than one parameter--the rightmost parameter is pushed first. Such mechanisms allow easier and more intuitive addressing of parameters within the function. Given the nature of a stack frame, we could access them as follows:
mov eax, [ebp + 8] ; Would load EAX with 128
mov eax, [ebp + 12] ; Would load EAX with 32
We are using an EBP register as the base pointer. The first (leftmost) parameter is located at offset 8 from the value stored in EBP, as the procedure's return address and the previously pushed value of EBP register occupy exactly 8 bytes. The following table shows the content of the stack after the creation of the stack frame:
Offset from EBP | Content |
+12 | rightmost parameter (32) |
+8 |
leftmost parameter (128) |
+4 |
procedure return address |
EBP points here |
previous value of EBP |
-4 |
first stack frame variable |
.... |
other stack frame variables |
.... |
saved registers |
ESP points here |
current stack position |