我已经拆解了两种不同的Swap函数变量(两个指针之间的简单值交换)。
1)。 __fastcall http://pastebin.com/ux5LMktz
2)。 __stdcall(没有显式调用约定修饰符的函数默认会有__stdcall,因为Windows的MS C ++编译器)http://pastebin.com/eGR6VUjX
据我所知,__ fastcall的实现方式不同,具体取决于编译器,但基本上它将前两个参数(从左到右)放入ECX和EDX寄存器。可能有堆栈使用,但如果参数太长。
但是对于1-st选项的链接,你可以看到,该值被推入ECX注册表,并且交换函数的两个变体之间没有真正的区别。
__fastcall变体确实使用:
00AA261F pop ecx
00AA2620 mov dword ptr [ebp-14h],edx
00AA2623 mov dword ptr [ebp-8],ecx
在__stdcall版本中没有使用。
所以它看起来不像是更优化的(因为__fasctcall必须是它的定义)。
我是ASM语言的新手并召集会议,所以我请教你一些建议。也许__fastcall在我的样本中更快,但是我没有看到它,是吗?
谢谢!
答案 0 :(得分:1)
尝试启用优化,然后比较结果。您的fastcall
版本有许多冗余操作,因为它没有进行优化。
以下是带有/Ox
的VS 2010的输出。
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
(您在示例中错误地称之为stdcall
):
_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