1

I have problem with inline asm in C++. I'm trying to implement fast strlen, but it is not working - when I use __declspec(naked) keyword debugger shows address of input as 0x000000, when I don't use that keyword, eax is pointing for some trash, and function returns various values.

Here's code:

   int fastStrlen(char *input) // I know that function does not calculate strlen
{                              // properly, but I just want to know why it crashes
    _asm                       // access violation when I try to write to variable x
    {
        mov ecx, dword ptr input
            xor eax, eax
        start:
            mov bx, [ecx]
            cmp bl, '\0'
            je Sxend
            inc eax
            cmp bh, '\0'
            je Sxend
            inc eax
            add ecx, 2
            jmp start
        Sxend:
            ret
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    char* test = "test";
    int x = fastStrlen(test);
    cout << x;
    return 0;
}

can anybody point me out what am I doing wrong?

5
  • You want mov not lea. Also, you are not returning the length, you are returning an address. Comparing 16 bit registers with '\0' isn't gonna do what you want either. By the way, this is not gonna be terribly fast, and you don't really need asm to do this. Commented Sep 1, 2014 at 17:48
  • @Jester mov neither works and yeah, I know that I'm returning now wrong val but I changed this because I thought the errors are because of use of ESI register ;_; Commented Sep 1, 2014 at 17:50
  • It ABI specific (so in practice depends upon the processor, the operating system, the compiler). Commented Sep 1, 2014 at 17:52
  • You must use eax for the return value. You can just zero it out after you do the loads, if you want. Also, you are not allowed to destroy ebx either. Commented Sep 1, 2014 at 17:54
  • @Jester soo I have to change - mov eax && eax as return && compare 8 byte reg with '\0'? Commented Sep 1, 2014 at 18:01

1 Answer 1

1

Don't use __declspec(naked) since in that case the complier doesn't generate epilogue and prologue instructions and you need to generate a prologue just like compiler expects you to if you want to access the argument fastStrlen. Since you don't know what the compiler expects you should just let it generate the prologue.

This means you can't just use ret to return to the caller because this means you're supplying your own epilogue. Since you don't know what prologue the compiler used, you don't know what epilogue you need implement to reverse it. Instead assign the return value to a C variable you declare inside the function before the inline assembly statement and return that variable in a normal C return statement. For example:

int fastStrlen(char *input)
{
    int retval;
    _asm
    {
        mov ecx, dword ptr input
        ...
    Sxend:
        mov retval,eax
    }
    return retval;
}

As noted in your comments your code will not be able to improve on the strlen implementation in your compiler's runtime library. It also reads past the end of strings of even lengths, which will cause a memory fault if the byte past the end of a string isn't mapped into memory.

Sign up to request clarification or add additional context in comments.

2 Comments

Unless the compiler is brain-dead, it should be able to reference arguments relative to esp without any prologue.
@Jester It could but then it would have to assume that the inline assembly didn't set up its own prologue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.