-2

我有这个代码块:

void CallAnyFunc(void *pfn, const std::vector<char> &arguments, CLR_DataType returnType, AnyFuncReturn &returnValue)
{
    int i4;
    float r4;
    double r8;
    long int i8;

    char* pStack;
    const char* i = arguments.empty() ? NULL : &*arguments.begin();
    const char* end = i + arguments.size();

    // Reserve the space on the stack
    // This is equivalent (in some sense) to 'push' all the parameters into the stack.
    // NOTE: Don't just subtract the stack pointer, better to call _alloca, because it also takes
    // care of ensuring all the consumed memory pages are accessible
#ifdef PLATFORM_WINDOWS
    _alloca(arguments.size());
#else
    alloca(arguments.size());
#endif

    _asm {
        mov pStack, esp
    };

    // Copy all the parameters into the stack
    // NOTE: Don't use the memcpy function. Because the call to it
    // will overwrite the stack (which we're currently building)
    while (i != end)
        *pStack++ = *i++;

    switch (returnType)
    {
        case DATATYPE_R4:
        {
            // Call your function
            _asm {
                call pfn
                fstp r4
            }

            returnValue.r4 = r4;
        } break;

        case DATATYPE_R8:
        {
            // Call your function
            _asm {
                call pfn
                fstp r8
            }

            returnValue.r8 = r8;
        } break;

        case DATATYPE_U8:
        case DATATYPE_I8:
        {
            // Call your function
            _asm {
                call pfn
                mov i8, eax
            }

            returnValue.i8 = i8;
        } break;

        default:
        {
            _asm {
                call pfn
                mov i4, eax
            };

            returnValue.i4 = i4;
        }
    }
}

基本上,它是调用 CLR 微点网的桥梁。

当我使用 xcode 提供的 gcc 进行编译时,我得到:

nmfi/nmf_call.cpp:153:no such instruction: `movlq %esp, -96(%rbp)'
nmfi/nmf_call.cpp:164:indirect call without `*'
nmfi/nmf_call.cpp:175:indirect call without `*'
nmfi/nmf_call.cpp:187:indirect call without `*'
nmfi/nmf_call.cpp:190:no such instruction: `movlq %eax, -88(%rbp)'
nmfi/nmf_call.cpp:197:indirect call without `*'

其中第 153 行 = mov pStack, esp 之后的行,第 190 行 = returnValue.i8 = i8 之后的行,这实际上是 mov i8, eax

...

这段代码可以正常工作。我认为更改是由于 x86_64 造成的,但在弄清楚如何正确编写“mov”以便可以组装时遇到问题。

...

相关编译器标志:

CC := g++
CFLAGS := -c -DLITTLE_ENDIAN=1 -DGCC_V4_2 -fasm-blocks  \
        -DVERSION_MAJOR="4" -DVERSION_MINOR="2" -DVERSION_BUILD="1" -DVERSION_REVISION="0" \
        -DOEMSYSTEMINFOSTRING='"OSXBOI"'

# -DMAC -fvisibility=hidden -fvisibility-inlines-hidden
AR := ar
ARFLAGS := rs

ifeq (,$(findstring Debug,$(CONFIG)))
    CFLAGS += -O3 -DNDEBUG
else
    CFLAGS += -g -D_DEBUG
endif

任何提示?

这是修改后的代码,未经测试,但可以编译。

void CallAnyFunc(void *_pfn, const std::vector<char> &arguments, CLR_DataType returnType, AnyFuncReturn &returnValue)
{
    int i4;
    float r4;
    double r8;
    long int i8;
    typedef void (*PFN)();
    PFN pfn = (PFN)_pfn;

    char* pStack;
    const char* i = arguments.empty() ? NULL : &*arguments.begin();
    const char* end = i + arguments.size();

    // Reserve the space on the stack
    // This is equivalent (in some sense) to 'push' all the parameters into the stack.
    // NOTE: Don't just subtract the stack pointer, better to call _alloca, because it also takes
    // care of ensuring all the consumed memory pages are accessible
#ifdef PLATFORM_WINDOWS
    _alloca(arguments.size());
#else
    alloca(arguments.size());
#endif

#ifdef X86_64
    _asm {
        mov pStack, rsp
    };
#else
    _asm {
        mov pStack, esp
    };
#endif

    // Copy all the parameters into the stack
    // NOTE: Don't use the memcpy function. Because the call to it
    // will overwrite the stack (which we're currently building)
    while (i != end)
        *pStack++ = *i++;

    switch (returnType)
    {
        case DATATYPE_R4:
        {
            // Call your function
            _asm {
                call *pfn
                fstp r4
            }

            returnValue.r4 = r4;
        } break;

        case DATATYPE_R8:
        {
            // Call your function
            _asm {
                call *pfn
                fstp r8
            }

            returnValue.r8 = r8;
        } break;

        case DATATYPE_U8:
        case DATATYPE_I8:
        {
#ifdef X86_64
            // Call your function
            _asm {
                call *pfn
                mov i8, rax
            }
#else
            _asm {
                call *pfn
                mov i8, eax
            }
#endif
            returnValue.i8 = i8;
        } break;

        default:
        {
#ifdef X86_64
            // Call your function
            _asm {
                call *pfn
                mov i4, eax
            }
#else
            _asm {
                call *pfn
                mov i4, eax
            }
#endif

            returnValue.i4 = i4;
        }
    }
}
4

1 回答 1

0

如果您正在构建 64 位代码,则指针和 long int 的大小都将是 64 位。为了获取地址的所有位,您可能希望使用rsp而不是指针。esp

对于i8变量,您有一些选择:将其保留为long int(或更好的是int64_t)并使用rax而不是eax. 或使其成为int32_t并继续使用eax.

于 2013-05-25T21:44:55.117 回答