I have disassembled two different variations of Swap function (simple value-swap between two pointers).

1). __fastcall http://pastebin.com/ux5LMktz

2). __stdcall (function without explicit calling convention modifier will have a __stdcall by default, because of MS C++ compiler for Windows) http://pastebin.com/eGR6VUjX

As I know, __fastcall is implemented differently, depending on the compiler, but basically it puts the first two arguments (left to right) into ECX and EDX register. And there could be stack use, but if the arguments are too long.

But as for the link at 1-st option, you can see, that value is pushed into the ECX registry, and there is no real difference between two variations of swap function.

And __fastcall variant does use:

00AA261F  pop         ecx  
00AA2620  mov         dword ptr [ebp-14h],edx
00AA2623  mov         dword ptr [ebp-8],ecx

Which are not used in __stdcall version.

So it doesn't look like more optimized (as __fasctcall must be , by its definition).

I'm a newbie in ASM language and calling convention, so I ask you for a piece of advice. Maybe __fastcall is faster exactly in my sample, but I don't see it, do I?

Thanks!

有帮助吗?

解决方案

Try turning on optimization, then comparing the results. Your fastcall version has many redundant operations because it's not optimized.

Here's output of VS 2010 with /Ox.

fastcall:

; _firstValue$ = ecx
; _secondValue$ = edx
?CallMe1@@YIXPAH0@Z PROC                ; CallMe1
    mov eax, DWORD PTR [ecx]
    push    esi
    mov esi, DWORD PTR [edx]
    cmp eax, esi
    je  SHORT $LN1@CallMe1
    mov DWORD PTR [ecx], esi
    mov DWORD PTR [edx], eax
$LN1@CallMe1:
    pop esi
    ret 0
?CallMe1@@YIXPAH0@Z ENDP                ; CallMe1

stdcall:

_firstValue$ = 8                    ; size = 4
_secondValue$ = 12                  ; size = 4
?CallMe2@@YGXPAH0@Z PROC                ; CallMe2
    mov edx, DWORD PTR _firstValue$[esp-4]
    mov eax, DWORD PTR [edx]
    push    esi
    mov esi, DWORD PTR _secondValue$[esp]
    mov ecx, DWORD PTR [esi]
    cmp eax, ecx
    je  SHORT $LN1@CallMe2
    mov DWORD PTR [edx], ecx
    mov DWORD PTR [esi], eax
$LN1@CallMe2:
    pop esi
    ret 8
?CallMe2@@YGXPAH0@Z ENDP                ; CallMe2

cdecl (what you mistakenly call stdcall in your example):

_firstValue$ = 8                    ; size = 4
_secondValue$ = 12                  ; size = 4
?CallMe3@@YAXPAH0@Z PROC                ; CallMe3
    mov edx, DWORD PTR _firstValue$[esp-4]
    mov eax, DWORD PTR [edx]
    push    esi
    mov esi, DWORD PTR _secondValue$[esp]
    mov ecx, DWORD PTR [esi]
    cmp eax, ecx
    je  SHORT $LN1@CallMe3
    mov DWORD PTR [edx], ecx
    mov DWORD PTR [esi], eax
$LN1@CallMe3:
    pop esi
    ret 0
?CallMe3@@YAXPAH0@Z ENDP                ; CallMe3
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top