为什么__fastcall assebmler 代码比 MS C++ 中的代码大__stdcall

Why is __fastcall assebmler code larger than __stdcall one in MS C++?

本文关键字:代码 stdcall C++ fastcall assebmler 为什么 MS      更新时间:2023-10-16

我已经拆解了两种不同的 Swap 函数变体(两个指针之间的简单值交换)。

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

2). __stdcall(没有显式调用约定修饰符的函数默认具有__stdcall,因为 MS C++ Windows 编译器)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在我的样本中正好更快,但我没有看到它,是吗?

谢谢!

尝试启用优化,然后比较结果。您的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