fastcall_caller
code:c++
/**
* @brief __fastcallのfuncを実行する。スタック除去のタイミングが問題にならないように実行できる
*
* @param arg_n funcの引数の数(最小3)
* @param func __fastcallの関数のポインタ
* @param arg0 1番目の引数
* @param arg1 2番目の引数
* @param arg2 3番目の引数
* @param ... 4番目以降の引数
* @return EAXでそのまま返す
*
* @note 引数が2個以下の場合はこの関数を経由する意味は無いため出来ないようにしました。func(arg0, arg1)で呼び出してください
* @warning 浮動小数や非32bitの引数は考慮していない
*/
inline __declspec(naked) intptr_t __cdecl fastcall_caller(int arg_n, void* func, intptr_t arg0, intptr_t arg1, intptr_t arg2, ...) {
__asm {
mov edx, ebp
mov ecx, dword ptr esp + 0x04
lea ebp, dword ptr esp - 0x0c
add ecx, 0x03
SHIFT_STACK:
mov eax, dword ptr ebp + 0x0c
mov dword ptr ebp, eax
add ebp, 0x04
loop SHIFT_STACK
mov dword ptr ebp, edx
mov dword ptr ebp + 0x04, esp
mov eax, dword ptr esp - 0x0c
mov dword ptr ebp + 0x08, eax
mov edx, dword ptr esp + 0x04
mov ecx, dword ptr esp
add esp, 0x08
call dword ptr esp - 0x0c
mov ecx, dword ptr ebp + 0x08
mov esp, dword ptr ebp + 0x04
mov dword ptr esp, ecx
mov ebp, dword ptr ebp
ret
}
}
この関数が作られた理由:AviUtl1.10のfastcallが呼び出し側でのスタック除去という特殊性があり、通常の呼び出しが出来なかったため。
__fastcallを実行して呼び出し側スタック除去が出来るようなコードを目的に作っていったわけですが、最終的にはfuncが関数側スタック除去でも正常に動作するようなものになりました。
旧
新たにpushして実行しているのが無駄
code:c++
/**
* @brief __fastcallのfuncを実行する。スタック除去のタイミングが問題にならないように実行できる
*
* @param func __fastcallの関数のポインタ
* @param arg_n funcの引数の数(最小3)
* @param arg0 1番目の引数
* @param arg1 2番目の引数
* @param arg2 3番目の引数
* @param ... 4番目以降の引数
* @return EAXでそのまま返す
*
* @note 引数が2個以下の場合はこの関数を経由する意味は無いため出来ないようにしました。func(arg0, arg1)で呼び出してください
* @warning 浮動小数や非32bitの引数は考慮していない
*/
inline __declspec(naked) intptr_t __cdecl fastcall_caller(void* func, int arg_n, intptr_t arg0, intptr_t arg1, intptr_t arg2, ...) {
__asm {
push ebp
mov ebp, esp
mov ecx, ebp + 12
sub ecx, 2
jg skip_arg_count_min
mov ecx, 1
skip_arg_count_min:
lea eax, ebp + 20 + ecx*4
push_args_loop:
push dword ptr eax
sub eax, 4
loop push_args_loop
mov ecx, ebp + 16
mov edx, ebp + 20
mov eax, ebp + 8
call eax
mov esp, ebp
pop ebp
ret
}
}
このサイトに書かれている内容について