kill15
kill15

Reputation: 33

Access to std::string in assembler (c++/asm/visual studio 2015)

I would like to ask how can I get single character and call std::string's function in asm.

When i compile code below i get:

   *Error   C2244    'std::basic_string<char,std::char_traits<char>,std::allocator<char>>::at': unable to match function definition to an existing declaration* 

My code:

   int main()
   {
      std::string mystring("Some characters");
      __asm 
     {
        push 1
        lea         ecx, [mystring]
        call std::string::at
      }
    return 0;
   }

Upvotes: 1

Views: 1664

Answers (2)

Peter Cordes
Peter Cordes

Reputation: 364947

Your undefined reference happens because of name-mangling to encode the argument types into the assembly/object-file symbol name. Also see Agner Fog's Optimizing Assembly guide, section 4.4 (pg30).

As has been mentioned in comments, your best bet is to look at compiler output. Also keep in mind that not all compilers use the same name-mangling scheme. Although using 32bit-MSVC-only inline asm syntax makes portability a non-issue.

Upvotes: 0

Slyps
Slyps

Reputation: 607

From MSDN:

An __asm block can call only global C++ functions that are not overloaded. If you call an overloaded global C++ function or a C++ member function, the compiler issues an error.

You can ( if you dare ) however do a very very ( can't stress this enough: very ) dirty hack. In this SO post, you can see ways and concerns of - I died a little while writing the following - obtaining the address of your member function.

std::string mystring("Some characters");

std::string::const_reference(__thiscall std::string::*atFunc)(std::string::size_type) const = &std::string::at;
unsigned int atAddress = PtrToUlong((void*&)atFunc); 
char output = 0;

__asm
{
    mov eax, atAddress

    push 5
    lea ecx, [mystring]
    call eax

    mov al, [eax]
    mov [output], al
}

std::cout << "Output is: " << output << std::endl;

If I were a supervisor, and one of my programmer minions would do this in production code, I would slap him/her with a big stinky fish. Use on your own risk.

The far more sane solution is to simply ditch any std::string usage from the __asm block:

std::string mystring("Some characters");
const char * cstr = mystring.c_str();
char output = 0;

__asm
{
    mov eax, [cstr]
    mov al, [eax+3]
    mov [output],al
}

std::cout << "Output is: " << output << std::endl;

Upvotes: 4

Related Questions