Namek Dev
a developer's log
NamekDev

C++ inline Assembler hack back in 2008

October 17, 2014

Digging deep in my work from past years I stumbled upon interesting Assembler workaround I made then for C++. I was looking for a solution that could make possible to wrap a class method into Function class object. These days with C++11 it’s just a matter of using std::bind and std::function but I think it’s pretty interesting to see what Assembler could be behind such “simple” task as encapsulating pointer to method.

I’ve found my code on my old pastebin account. There are few things I don’t like in it, so please, don’t comment on it, I don’t like it either :) I’ve just translated comments and code is left as original, gist here.

And here I present the most interesting part, just look at that hacky Assembler:

int Callback::callInt( void* par )
{
    if( par != NULL )
    {
        setPar( par );
    }

    if( m_bIsInstantiated )
    {
        void* pFunc = (void*) m_pFunc;
        void* pThis = m_pThis;

        int dSize = 0;
        int dNumParameters = m_dNumParameters;
        int dOut = 0;

        // here paramters are set in proper convention's call order
        int* pParameter = m_vpParameters;
        __asm
        {
            mov ecx, 0                        // nullify iterator

                                              // while( true )
            our_for:                          // {

                cmp ecx, [dNumParameters]     // if( i < dNumParameters )
                jae end_our_for               // goto end_our_for;

                mov ebx, pParameter           // put parameter on the stack
                push [ebx]

                add ecx, 1                    // i++;

                add dSize, 4                  // increase the stack size
                add pParameter, 4             // choose next parameter pointer

                jmp our_for       

            end_our_for:                      // }


            mov ecx, pThis;              // call the function
            call pFunc;                  //

            add esp, [dSize]            // clear the stack
           
            mov [dOut], eax;            // put the `int` result into `dOut` variable.
                                        // It's only needed for `callInt` but
                                        // it's no error to use it in void function.
        }
     
        return dOut;
    }

    // for compiler's happiness
    return 0;
}

Here is the usage:

SomeClass obj;
Callback d( 1, &obj, &SomeClass::someMethod, 0 );

d.call();

The full code is here on gist.

Time passed

Here on StackOverflow you can see today’s solutions.

I made this around 2008. But Internets. Internets do have almost everything and I have found that there existed a published solution since 2004 which I didn’t know about!

This shows how programming languages, technologies and community evolve which is a nice thing.

c++
comments powered by Disqus