简体   繁体   中英

How to pass float as argument (inline-assembly)?

How to pass float as function argument (external call) and return float in inline assembly? An example below doesn't work and is crashing the app. The comments are mine, so they might be also wrong.

The first two lines are added by myself just for this example. Originally I start with two float values on st(0) and st(1) and there's nothing I can do about that.

fld     a               ; load float 'a' on st(0)
fld     b               ; load float 'b' on st(0), 'a' is now st(1)
sub     esp, 4          ; make room for float 
fstp    dword ptr [esp] ; push st(0) on stack, pop st(0)
mov     ecx, ebp        ; move 'this' on ecx
call    Class::ModValue ; returns float on st(0)
fcompp                  ; compare returned st(0) with st(1)    
fnstsw  ax
test    ah, 41h
jnz     Exit_label

The code snippet above is inside asm{} block, there is more unimportant code before and after that. The crash is happening between 1st line of this code fragment and ModValue function call.

Function signature:

float Class::ModValue(float value)
{
    _LOG("ModValue") // doesn't show
    return value;
}

Compiler: VisualStudio, Architecture: x86, Calling convention: __thiscall

if it's a __thiscall

According to msdn:

The __thiscall calling convention is used on member functions and is the default calling convention used by C++ member functions that do not use variable arguments. Under __thiscall, the callee cleans the stack, which is impossible for vararg functions. Arguments are pushed on the stack from right to left, with the this pointer being passed via register ECX, and not on the stack, on the x86 architecture.

source: https://msdn.microsoft.com/en-us/library/ek8tkfbw.aspx

then a small example:

float DoStuffs(void *pThis, float a)
{
    float flResult = 0.0f;

    __asm
    {
        push a;
        mov ecx, pThis;
        call Class::ModValue;
        fstp[flResult];
    }
    return flResult;
}

Some extended example:

class Test
{
public:
    float b;   
    float Add(float a);

};

float Test::Add(float a)
{
    return a + this->b;
}

float CallTest(void* pThis, float x)
{
    float flResult = 0.0f;

    __asm
    {
        push x;
        mov ecx, pThis;
        call Test::Add;
        fstp[flResult];
    }

    return flResult;
}

int main()
{
    void* m = malloc(4);

    *(float*)m = 2.0f;

    std::cout << CallTest(m, 2.1f) << std::endl;

    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM