我反汇编了 Swap 函数的两种不同变体(两个指针之间的简单值交换)。
1). __快速调用http://pastebin.com/ux5LMktz
2). __stdcall(没有显式调用约定修饰符的函数在默认情况下将具有 __stdcall,因为适用于 Windows 的 MS C++ 编译器)http://pastebin.com/eGR6VUjX
据我所知,__fastcall 的实现方式因编译器而异,但基本上它将前两个参数(从左到右)放入 ECX 和 EDX 寄存器。并且可以使用堆栈,但如果参数太长。
但是对于第一个选项的链接,您可以看到,该值被推送到 ECX 注册表中,并且交换功能的两种变体之间没有真正的区别。
并且 __fastcall 变体确实使用:
00AA261F pop ecx
00AA2620 mov dword ptr [ebp-14h],edx
00AA2623 mov dword ptr [ebp-8],ecx
在 __stdcall 版本中未使用。
所以它看起来不像更优化(因为 __fasctcall 必须是 ,根据其定义)。
我是 ASM 语言和调用约定方面的新手,所以我请教您一些建议。也许 __fastcall 在我的示例中确实更快,但我没有看到它,是吗?
谢谢!
最佳答案
尝试打开优化,然后比较结果。您的 fastcall
版本有很多冗余操作,因为它没有优化。
这是带有 /Ox
的 VS 2010 的输出。
快速调用
:
; _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
标准调用
:
_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
关于c++ - 为什么 __fastcall assebmler 代码大于 MS C++ 中的 __stdcall 代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18684214/