.NET Framework のクラスライブラリが使う __clrcall を解析してみたら __fastcall のパクリだった件
引数3つ以上指定したら dllexport が動かなくなったので呼び出し規約が違うのでは?
と思い当たって調べてみたら __clrcall というのを使ってるらしい。
そこで、逆アセンブルしてみてみた。
int x =main(1, 2, 3,4,5,6,7); 00007FFDC4B00147 mov dword ptr [rsp+30h],7 00007FFDC4B0014F mov dword ptr [rsp+28h],6 00007FFDC4B00157 mov dword ptr [rsp+20h],5 00007FFDC4B0015F mov r9d,4 00007FFDC4B00165 mov r8d,3 00007FFDC4B0016B mov edx,2 00007FFDC4B00170 mov ecx,1 00007FFDC4B00175 call 00007FFDC49CC020 |
なるほどわからん。x64になってた・ω・
x = main(2, 3, 4, 4, 5, 6, 7); 04E600C7 push 4 04E600C9 push 4 04E600CB push 5 04E600CD push 6 04E600CF push 7 04E600D1 mov edx,3 04E600D6 mov ecx,2 04E600DB call 00B6C010 04E600E0 mov dword ptr [ebp-48h],eax |
一つ目の引数は ecx, 2つ目の引数は edx, 3つ目の引数は以降スタックに積んで呼び出すらしい。
__fastcall に似ている?
int x =main(2, 3, 4,4,5,6,7); 0041298B 6A 07 push 7 0041298D 6A 06 push 6 0041298F 6A 05 push 5 00412991 6A 04 push 4 00412993 6A 04 push 4 00412995 BA 03 00 00 00 mov edx,3 0041299A B9 02 00 00 00 mov ecx,2 0041299F E8 97 E7 FF FF call @ILT+310(@main@28) (41113Bh) 004129A4 89 45 DC mov dword ptr [ebp-24h],eax |
と思って比べてみたら、一緒だった ・ω・
00007FF74A9E1086 C7 44 24 30 07 00 00 00 mov dword ptr [rsp+30h],7 00007FF74A9E108E C7 44 24 28 06 00 00 00 mov dword ptr [rsp+28h],6 00007FF74A9E1096 C7 44 24 20 05 00 00 00 mov dword ptr [rsp+20h],5 00007FF74A9E109E 41 B9 04 00 00 00 mov r9d,4 00007FF74A9E10A4 41 B8 04 00 00 00 mov r8d,4 00007FF74A9E10AA BA 03 00 00 00 mov edx,3 00007FF74A9E10AF B9 02 00 00 00 mov ecx,2 00007FF74A9E10B4 E8 4C FF FF FF call xmain (7FF74A9E1005h) 00007FF74A9E10B9 89 44 24 40 mov dword ptr [x],eax |
x64もみてみたけど同じっすね…
結論 __clrcall は __fastcall と同じ! なんで、インターネット上に情報ないんだよ!
引数の渡し規則と名前付け規則 | Microsoft Docs
キーワード スタック クリーンアップ パラメーター渡し
__cdecl Caller パラメーターをスタックに逆の順序で (右から左に) プッシュする
__clrcall 該当なし CLR 式スタックに順に (左から右に) パラメーターを読み込む
__stdcall Callee パラメーターをスタックに逆の順序で (右から左に) プッシュする
__fastcall Callee レジスタに格納されてから、スタックにプッシュされる
__thiscall Callee スタックにプッシュされます。 this ECX に格納されているポインター
__vectorcall Callee レジスタに格納されてから、スタックに逆の順序で (右から左に) プッシュされる
まるで、__clrcall と __fastcall が違うような書き方だな、おいw
パクりましたとかだと著作権問題になるからかな( ˘ω˘ )?
あ、もしかして、DLLEXPORTできない理由も情報を公開したくない、そういう事か!
もしかすると、CPUや返り値によって独自の拡張がされてる可能性はあるのかな・ω・
少なくとも__fastcallはMicrosoftとEmcarcadero/Borlandで異なります。
MSDNで明記されていない通り、実装依存ですよ。