1

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;
   }

kill15
  • 13
  • 3
  • 2
    Write C code that does what you want and then look at the compiler's output. – David Schwartz Aug 28 '15 at 19:37
  • when i write: int main() { std::string mystring("Some characters"); mystring.at(1); return 0; } I get(after dissasembly): mystring.at(1); 00E65714 push 1 00E65716 lea ecx,[mystring] 00E65719 call std::basic_string,std::allocator >::at (0E616EAh) And it's exactly the same what i wrote in first post. The same error. – kill15 Aug 28 '15 at 19:54

2 Answers2

4

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;
Community
  • 1
  • 1
Slyps
  • 607
  • 4
  • 9
  • Reminder: the `std::string::at` is a **C++ member function** (just highlighting the relationship). – Thomas Matthews Aug 28 '15 at 20:39
  • Yea, It cannot regonizes function when function is overloaded. Is there any way to get single character directly from std::string? i'm just learning and i'm curious because these characters are somewhere in memory. Thank you for your answers – kill15 Aug 28 '15 at 20:47
  • @kill15 You can access the returned pointer by `std::string::c_str()` and write your own "`at`"-function in asm. – Slyps Aug 28 '15 at 20:53
  • @kill15 I added such a solution to the answer. Beware, it doesn't check bounds or anything else. – Slyps Aug 28 '15 at 21:00
  • Thank you, i was only curious if it is possible. – kill15 Aug 28 '15 at 21:03
0

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.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847