8

I am using Visual C++ 2010, and MASM as my x64-Assembler.
This is my C++ code:

// include directive
#include "stdafx.h"
// functions
extern "C" int Asm();
extern "C" int (convention) sum(int x, int y) { return x + y; }
// main function
int main()
{
    // print asm
    printf("Asm returned %d.\n", Asm());
    // get char, return
    _getch();
    return EXIT_SUCCESS;
}

And my assembly code:

; external functions
extern sum : proc
; code segment
.code
Asm proc
    ; create shadow space
    sub rsp, 20o
    ; setup parameters
    mov ecx, 10
    mov edx, 15
    ; call
    call sum
    ; clean-up shadow space
    add rsp, 20o
    ; return
    ret
Asm endp
end

The reason I am doing this is so I can learn the different calling conventions. I would make sum's calling convention stdcall, and modify the asm code so it would call sum the "stdcall" way. Once I got that working, I would make it, say, fastcall, and then call it in asm the "fastcall" way.

But look at my assembly code right now. When I use that code, no matter if sum is stdcall, fastcall or cdecl, it will compile, execute fine, and print 25 as my sum.

My question: How, and why can __cdecl, __stdcall and __fastcall all be called the exact same way?

Praetorian
  • 106,671
  • 19
  • 240
  • 328
Name
  • 2,037
  • 3
  • 19
  • 28

2 Answers2

12

The problem is that you're compiling for x64 targets. From MSDN

Given the expanded register set, x64 just uses the __fastcall calling convention and a RISC-based exception-handling model. The __fastcall model uses registers for the first four arguments and the stack frame to pass the other parameters.

Switch over to compiling for x86 targets, and you should be able to see the various calling conventions in action.

Praetorian
  • 106,671
  • 19
  • 240
  • 328
  • 3
    "When compiling for the x64 architecture in a Windows context (whether using Microsoft or non-Microsoft tools), there is only one calling convention — the one described here, so that stdcall, thiscall, cdecl, fastcall, etc., are now all one and the same." http://en.wikipedia.org/wiki/X86_calling_conventions – Hugo Corrá Feb 24 '13 at 01:52
  • Okay... I'm just gonna switch over to x86 and try to compile with different calling conventions and see what the results are, just to check if this is what it's doing. When that likely works, I'll accept your answer :) – Name Feb 24 '13 at 01:56
  • Okay, I have another question. Let's say I wanted to call some Win32 function, perhaps [Sleep](http://msdn.microsoft.com/en-us/library/windows/desktop/ms686298(v=vs.85).aspx), while I'm in x64 assembly. Since Sleep has already been compiled, would I use the fastcall convention, or Sleep's convention (which is stdcall, in this case)? – Name Feb 24 '13 at 02:15
  • @JesusPlusPlus I'm not absolutely sure about this, but when you're compiling for x64, you should be linking to the 64-bit version of kernel32.lib (the library that Sleep is defined in). In that case, that function will also be using __fastcall. However, Sleep from the 32-bit version of kernel32.lib will use __stdcall calling convention. – Praetorian Feb 24 '13 at 02:42
  • @JesusPlusPlus Your follow-up question makes no sense. if A == B, then there's no point asking "Should I use A or B?" On x64, fastcall == stdcall == cdecl, so use any one you want, they're all the same. – Raymond Chen Feb 24 '13 at 04:52
  • @RaymondChen I'm sorry, second question wasn't very clear. What's happening is that I'm trying to call Sleep in x64, but I get an access violation error when I call it the "fastcall way". I'm wondering why this is. – Name Feb 24 '13 at 16:27
  • It looks like you misaligned the stack. The stack needs to be 16-byte aligned. Make sure you're following all the rules in the x64 ABI It's also not clear why you are doing this all manually in the first place. Just write it in C/C++ and let the compiler worry about it. `Sleep` is not going to be performance-sensitive code; there's no practical reason to write it in assembly. If you want to see how it's done, just compile your C program and look at what the compiler generated. – Raymond Chen Feb 24 '13 at 16:31
  • @RaymondChen I'm learning assembly because I'm curious about the inner-workings of the computer; I completely understand how unpractical it is. Anyway, thanks for the answer, I'll look into the x64 ABI rules. – Name Feb 24 '13 at 16:34
5

As far as i know x64 only uses the __fastcall convention. __cdecl and stdcall will just be compiled as __fastcall.

user1283078
  • 2,006
  • 17
  • 17