CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8
  1. #1
    George2 is offline Elite Member Power Poster
    Join Date
    Oct 2002
    Posts
    4,468

    calling convention stdcalll and cdecl call

    Hello everyone,


    Both stdcall and cdecl calling convention could support variable input parameters? Is that correct?

    (I think stdcall is using RET N and cdecl is using ESP - N, so both are capable to handle variable number of input parameter, like printf?)

    BTW: I have this question because I have something in mind that only one of them supports variable number of parameters, but after reading assembly language code, I think both of them are able to support this feature?


    thanks in advance,
    George

  2. #2
    Join Date
    Jun 2005
    Posts
    1,255

    Smile Re: calling convention stdcalll and cdecl call

    Yes, both stdcall and cdecl calling conventions support variable input parameters. The difference is that the stack pointer is reset by the callee with stdcall, and the stack pointer is reset by the caller with cdecl.

    The isssue of variable arguments depends on the argument passing order and the syntax of your functions.
    With the C (stdcall or cdecl) order, arguments are passed from right to left, whereas with the Pascal order, arguments are passed from left to right.

    Let's look at printf("x=%d", y=%d", x, y);
    Let's say the stack pointer is 100 before the call.
    Three arguments are pushed onto the stack.
    With the C order (stdcall and cdecl), we have:
    push y ; stack pointer is 96
    push x ; stack pointer is 92
    push address of "x=%d", y=%d" ; stack pointer is 88.
    Inside printf, the program will examine the argument which is the closest to the stack pointer, ie. address of "x=%d", y=%d", and will find that there are two percent signs, therefore two more arguments on the stack.

    With the Pascal order
    push address of "x=%d", y=%d" ; stack pointer is 96.
    push x ; stack pointer is 92
    push y ; stack pointer is 88
    Inside printf, the program will examine the argument which is the closest to the stack pointer, ie. y. Now, the program does not know if there are other arguments. However, with this convention, variable arguments are possible if printf() syntax were changed in order to have the format string at the end instead of at the beginning.

  3. #3
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: calling convention stdcalll and cdecl call

    Both stdcall and cdecl calling convention could support variable input parameters? Is that correct?
    MSDN, C++ Language Reference
    __stdcall

    Microsoft Specific

    The __stdcall calling convention is used to call Win32 API functions. The callee cleans the stack, so the compiler makes vararg functions __cdecl.
    The proof:
    Code:
    // 445.cpp
    int __stdcall foo(int a, char c, ...) { return 0; }
    Code:
    E:\Temp\445>cl 445.cpp /c
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
    Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.
    
    445.cpp
    
    E:\Temp\445>dumpbin /SYMBOLS 445.obj
    Microsoft (R) COFF/PE Dumper Version 7.10.3077
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    
    Dump of file 445.obj
    
    File Type: COFF OBJECT
    
    COFF SYMBOL TABLE
    000 00000000 DEBUG  notype       Filename     | .file
        445.cpp
    002 00600C05 ABS    notype       Static       | @comp.id
    003 00000001 ABS    notype       Static       | @feat.00
    004 00000000 SECT1  notype       Static       | .drectve
        Section length   2A, #relocs    0, #linenums    0, checksum        0
    006 00000000 SECT2  notype       Static       | .debug$S
        Section length   5A, #relocs    0, #linenums    0, checksum        0
    008 00000000 SECT3  notype       Static       | .text
        Section length    7, #relocs    0, #linenums    0, checksum 96F779C9
    00A 00000000 SECT3  notype ()    External     | ?foo@@YAHHDZZ (int __cdecl foo(int,char,...))
    
    String Table Size = 0x12 bytes
    
      Summary
    
              5A .debug$S
              2A .drectve
               7 .text
    See the difference.
    Last edited by Igor Vartanov; July 17th, 2008 at 06:10 AM.
    Best regards,
    Igor

  4. #4
    Join Date
    Feb 2000
    Location
    San Diego, CA
    Posts
    10,354

    Re: calling convention stdcalll and cdecl call


  5. #5
    George2 is offline Elite Member Power Poster
    Join Date
    Oct 2002
    Posts
    4,468

    Re: calling convention stdcalll and cdecl call

    Thanks olivthill,


    I do not fully agree with you that both stdcall and cdecl call support variable input parameters. Please refer to Igor's comment below and find only cdecl supports variable input parameter feature. Any comments?

    Quote Originally Posted by olivthill
    Yes, both stdcall and cdecl calling conventions support variable input parameters. The difference is that the stack pointer is reset by the callee with stdcall, and the stack pointer is reset by the caller with cdecl.

    The isssue of variable arguments depends on the argument passing order and the syntax of your functions.
    With the C (stdcall or cdecl) order, arguments are passed from right to left, whereas with the Pascal order, arguments are passed from left to right.

    Let's look at printf("x=%d", y=%d", x, y);
    Let's say the stack pointer is 100 before the call.
    Three arguments are pushed onto the stack.
    With the C order (stdcall and cdecl), we have:
    push y ; stack pointer is 96
    push x ; stack pointer is 92
    push address of "x=%d", y=%d" ; stack pointer is 88.
    Inside printf, the program will examine the argument which is the closest to the stack pointer, ie. address of "x=%d", y=%d", and will find that there are two percent signs, therefore two more arguments on the stack.

    With the Pascal order
    push address of "x=%d", y=%d" ; stack pointer is 96.
    push x ; stack pointer is 92
    push y ; stack pointer is 88
    Inside printf, the program will examine the argument which is the closest to the stack pointer, ie. y. Now, the program does not know if there are other arguments. However, with this convention, variable arguments are possible if printf() syntax were changed in order to have the format string at the end instead of at the beginning.

    regards,
    George

  6. #6
    George2 is offline Elite Member Power Poster
    Join Date
    Oct 2002
    Posts
    4,468

    Re: calling convention stdcalll and cdecl call

    Thanks Igor,


    What is the root cause why stdcall does not support variable number of input parameter? Maybe from generated assembly, we could find out?

    (I think both caller and callee could get # of input parameters from stack in theory?)


    regards,
    George

  7. #7
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: calling convention stdcalll and cdecl call

    Quote Originally Posted by George2
    Thanks Igor,

    What is the root cause why stdcall does not support variable number of input parameter? Maybe from generated assembly, we could find out?
    Exactly!

    Let's see, the very basic sample:
    Code:
    // 446cdecl.cpp
    int __cdecl foo(int a, char c, ...) { return 0; }
    int main() { return foo(0, 0, 0); }
    Code:
    // 445stdcall.cpp
    int __stdcall foo(int a, char c) { return 0; }
    int main() { return foo(0, 0); }
    Compile along with producing ASM:
    Code:
    cl 446cdecl.cpp /c /FA && cl 446stdcall.cpp /c /FA
    Code:
    PUBLIC	?foo@@YAHHDZZ					; foo
    ; Function compile flags: /Odt
    _TEXT	SEGMENT
    _a$ = 8							; size = 4
    _c$ = 12						; size = 1
    ?foo@@YAHHDZZ PROC NEAR					; foo
    ; File e:\temp\446\446cdecl.cpp
    ; Line 1
    	push	ebp
    	mov	ebp, esp
    	xor	eax, eax
    	pop	ebp
    	ret	0
    ?foo@@YAHHDZZ ENDP					; foo
    _TEXT	ENDS
    PUBLIC	_main
    ; Function compile flags: /Odt
    _TEXT	SEGMENT
    _main	PROC NEAR
    ; Line 2
    	push	ebp
    	mov	ebp, esp
    	push	0
    	push	0
    	push	0
    	call	?foo@@YAHHDZZ				; foo
    	add	esp, 12					; 0000000cH
    compiler knows exactly the size of the stack on the caller side
    	pop	ebp
    	ret	0
    _main	ENDP
    Code:
    PUBLIC	?foo@@YGHHD@Z					; foo
    ; Function compile flags: /Odt
    _TEXT	SEGMENT
    _a$ = 8							; size = 4
    _c$ = 12						; size = 1
    ?foo@@YGHHD@Z PROC NEAR					; foo
    ; File e:\temp\446\446stdcall.cpp
    ; Line 1
    	push	ebp
    	mov	ebp, esp
    	xor	eax, eax
    	pop	ebp
    	ret	8                          ; the function body knows the 
                                             ; exact size of stack to be cleared 
                                             ; (defined by function prototype) 
                                             ; but knows nothing about the actual stack size used
    ?foo@@YGHHD@Z ENDP					; foo
    _TEXT	ENDS
    PUBLIC	_main
    ; Function compile flags: /Odt
    _TEXT	SEGMENT
    _main	PROC NEAR
    ; Line 2
    	push	ebp
    	mov	ebp, esp
    	push	0
    	push	0
    	call	?foo@@YGHHD@Z				; foo
    	pop	ebp
    	ret	0
    _main	ENDP
    (I think both caller and callee could get # of input parameters from stack in theory?)
    Yep, maybe in theory. But not in practice.
    Attached Files Attached Files
    Best regards,
    Igor

  8. #8
    George2 is offline Elite Member Power Poster
    Join Date
    Oct 2002
    Posts
    4,468

    Re: calling convention stdcalll and cdecl call

    Thanks Igor!


    I think the reason why stdcall can not have variable number of input parameter is, we can not have a common code which is capable to pop variable number of input parameters (a specific function is common code base, and needs common code to pop a specific number (not variable) of elements from stack, but if input parameter number is variable, it is impossible to have such a common code base), correct?


    regards,
    George

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured