Indexing args as an array in the Windows x86-64 ABI [closed]

只愿长相守 提交于 2019-12-14 00:08:52

问题


I'm trying to port a wrapper function from 32bit to x86-64 asm for the Windows ABI. The function depends on indexing into its arguments as an array.

I know that MSVC cannot do inline assembly in X64 projects, but i am interested to build the equivalent function into a X64 .asm file.

The function sets the stackframe for the api to be called.

__declspec( naked ) PVOID WINAPIV CGX86( FARPROC lpPtr, UINT lpSize, ... )
{
    __asm {
        push ebp;
        mov ebp, esp;
        lea eax, [ ebp + 0x04 ];
        mov [ ebp - 0x04 ], eax;
        mov eax, [ ebp - 0x04 ];
        mov ecx, [ ebp + 0x0C ];
        add ecx, 2;
ParseArgs:
        cmp ecx, 2;
        jz short MoveFinal;
        push dword ptr [ eax + ecx * 0x04 ];
        sub ecx, 1;
        jmp short ParseArgs;
MoveFinal:
        call [ ebp + 0x08 ];
        mov esp, ebp;
        pop ebp;
        retn;
    }
}

example use:

CGX86( ( FARPROC )MessageBoxA, 4, GetForegroundWindow( ), "BODY", "TITLE", MB_OK );

回答1:


Jester's suggestion to write it in C is probably a good one, esp. if it can be inlined into calls where some of the args are compile-time constants. Your example use-case passes mostly compile-time-constant args, including the function pointer. Any decent optimizing compiler will inline this and optimize away the indirection into just a normal function call with the right args. Make sure you put the definition somewhere it can be inlined.


However, if you can't get the compiler to make nice code:

Indexing arguments as an array is the only piece of functionality that's non-obvious how to implement in the 64bit ABI where some args are in regs.

The Windows 64bit calling convention provides space for storing the 4 register args right below the stack args (the shadow space), so you actually can create an array of args you can index with only at most 4 instructions (store the args into those slots). You don't need to special-case the first 4 args.

Don't forget to put the outgoing args into regs instead of the stack, too, and leave shadow-space for the function you call.

As Ross Ridge points out, make sure you include directives to create SEH unwind info in the stand-alone asm. This is another good reason to favour a pure C++ solution, esp. if the number of args is limited to a small number.

See the x86 tag wiki for links to calling conventions and so on.

I'm not a fan of the Windows calling convention in general, but it does make implementing var-args functions simple. I'm pretty sure that's why the "shadow space" exists in the ABI.



来源:https://stackoverflow.com/questions/36851216/indexing-args-as-an-array-in-the-windows-x86-64-abi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!