6

I am trying to learn ASM, and want to try a few things combined with C++. The ASM part is done in a naked function. But whenever I call the function (empty) the application crashes in the next function. What should I do in the naked function to make it work, do I need to pop esp or something? An example could be helpfull.

_declspec(naked) void asmfunc()
{
    _asm
    {
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    i = 1;

    asmfunc();

    cout << i << endl; // <-- crash
    system("pause");

    return 0;
}
Paul R
  • 208,748
  • 37
  • 389
  • 560
  • 2
    As specified by the [documentation](http://msdn.microsoft.com/it-it/library/h5w10wxs.aspx), you need to write the prolog/epilog code; see [this question](http://stackoverflow.com/questions/3021513/could-someone-explain-declspecnaked-please). Also, consider if you really need `naked` functions: if all you want is to write some embedded assembly just use a regular function and let the compiler deal with C++ calling conventions. – Matteo Italia Jul 08 '12 at 18:02
  • 3
    Pay attention to the calling conventions. Naked functions do not preserve the required registers. – Mysticial Jul 08 '12 at 18:02

2 Answers2

15

Naked function will not contain any compiler-generated prologue and epilogue code. That applies to the implicit return statement at the end of the function as well.

That means that the function you declared has no ret instruction at the end. Once the control is transferred to asmfunc, it never returns. The function continues to execute whatever code exists at that location until it hits something that makes it crash.

Basically, your original implementation of asmfunc works as a label somewhere in the middle of the program code. And when you call your function, you are essentially doing a goto asmfunc, i.e. you transfer control somewhere without any hope of return.

For this reason, a minimal naked function should look as

_declspec(naked) void asmfunc()
{
    _asm
    {
      ret
    }
}

It is your responsibility to place ret instructions into a naked function.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • 1
    *And when you call your function, you are essentially doing a `goto asmfunc`* That's not quite right. The (compiler-generated) caller still uses `call` to push a return address, the callee just fails to use it. Instead it falls into the next function, or maybe hits an `int3` (debug-break) instruction because that's what MSVC pads with between functions. IDK whether `asmfunc` would end up pointing to padding, or would have the same address as some other function, if you make it naked with no instructions. (Anyway yes that's the bug, I'm just disputing the description of what happens.) – Peter Cordes May 28 '18 at 07:19
  • some reason you can't just use `return;` instead of `_asm{ret}` ? – hanshenrik Jul 16 '18 at 10:57
1

The naked function in c language programs doesn't contain prologue and epilogue code which prepare a function to do a task. so this is your job to make prologue and epilogue code. in the following code, you see I define prologue and epilogue and you can define your assembly code there.

__declspec(naked) void NakedFunction() {
    __asm {
        push ebp
        mov ebp, esp
    }

    __asm {
        // write your code here
    }

    __asm {
        leave
        ret
    }
}

int main() {
    NakedFunction();

    return 0x0;
}
  • If you want a traditional stack-frame prologue / epilogue, you probably don't need a naked function in the first place. Part of the point of using `__declspec(naked)` is to be able to leave out those unnecessary instructions, or to return in a non-standard way. Or put a block of code for the slow case after the `ret` for the fast path. (i.e. lay out your branches to the last instruction in the function isn't a `ret`, but instead a `jmp` back to the main part of your function.) – Peter Cordes May 28 '18 at 07:23