CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4
  1. #1
    Join Date
    Jan 2010
    Posts
    53

    Why Inline asm in C++/CLI creates horrible problem?

    Hello,

    I am extremely begginer and at at most novice level for playing with assembly.

    I am using Inline asm in C++/CLI. Horrible problem infact could be a bug I obsereved. I passed vector from one function call to another. If I comment the whole code snippet of _asm{....some assembly code here} inside the called function where vector used which are provided to it from other function, then no problem whole vector gets fine and copied to argument of called function successfully in correct manner.

    But If uncomment _asm{} I mean if I use _asm{} patch in called function , it corrupts the whole vectors of objects, even single string which is participating as in parameter to the function .Infact every most of arguments as data of called function get corrupts where _asm code used. It just shows for every argument values like npos=4294967295. I was expecting string argument would contain valid "strings" and all other rest of parameter would have their correct states. which I just passed from other functions to that called function.


    I am amazed while debugging the exe that even before reaching to the point of "_asm" at code , whole data before "_asm" place gets corrupts. Its just like unbelieveable.

    EVEN IF I COMMENT EVERYTHING INSIDE _asm PATCH, AND HAVING JUST _asm{} EMPTY OPENING CLOSING BRACES AFTER _asm KEYWORD, STILL THE PROBLEM HAPPENS

    Here If I dont write anything at all inside _asm{} even then problem occurs which I described.

    What is it? Why this is so? Is CLI creating problem or I am using inline asm in wrong way?
    Do I need to save the states of registers?

    Kindly help me out , as I am stuck here.

    example code:

    strParamType = strReturnType;
    if(strParamType.find("IDispatch")!=string::npos)
    {
    IDispatch* pIDispatch;
    _asm
    {
    mov esi,esp
    lea eax,[pIDispatch]
    push eax
    }
    }



    Regards

  2. #2
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    Re: Why Inline asm in C++/CLI creates horrible problem?

    I'm baffled by the fact that you even could get code containing inline assembly to compile in the C++/CLI environment. Inline assembly completely makes no sense in source code that is supposed to get compiled to managed code.

    Have you tried to enclose the function that contains the inline assembly code between #pragma managed(push,off) and #pragma managed(pop) directives? This would force that particular function to be compiled to native code and might help you out of (at most) part of the trouble you're facing.

    And what do you suppose your assembly snippet to do? It makes completely no sense to me, neither in managed nor native code. It would pretty sure mess up the stack and force your program to crash.

    And if you want to experiment with inline assembly, why don't you do that in a native project?

    I'm not completely sure about which registers you would have to preserve in inline assembly code meant to be used with code generated by the current VC++ compiler. To be on the safe side, you may want to preserve everything except the registers EAX and EDX, and the flags that are affected by ordinary arithmetic and logic operations.

    HTH

  3. #3
    Join Date
    Jan 2010
    Posts
    53

    Re: Why Inline asm in C++/CLI creates horrible problem?

    I am using #pragma(push,off) for native code compilation. More over I want to stay here at .NET and need to get equivalent power of native C++.

    This time code base is large in volume and cannot be shifted directly in native environment, More over some other reasons force me to write code in C++/CLI probably interacting with managed named pipes and WCF.

    Here forget about code snippet if it creates the problem in terms of messing up stack.

    Even If I just write _asm{} no code , no instruction inside block of asm and just openign and closing

    amazingly IT JUST CREATES THE PROBLEM STILL.
    So Why this is so...?

    Again I am working with #pragma managed(push,off) for native code.

  4. #4
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    Re: Why Inline asm in C++/CLI creates horrible problem?

    Weird. So I did some experiments with a C++/CLI console project.

    First step: empty __asm block: works.

    Then I took the __asm block from the message box example I posted in another thread here in this section, that is known to work in the native environment, and transplanted it to the C++/CLI project. This is the __asm block:

    Code:
      __asm {
        xor   eax,eax
        push  eax
        push  eax
        push  offset achMessage
        push  eax
        call  dword ptr [MessageBox]
      }
    I could successfully get past displaying the message box but got kicked out with an AccessViolationException upon return from the native function.

    Then I tried to call the MessageBox() API function the C way, and it worked. This is what the compiler generated for this call:

    Code:
      MessageBox(NULL,achMessage,NULL,0);
    00401A42 6A 00                push        0  
    00401A44 6A 00                push        0  
    00401A46 68 68 55 40 00       push        offset _achMessage (405568h)  
    00401A4B 6A 00                push        0  
    00401A4D E8 FE F7 FF FF       call        _t2m@_MessageBox (401250h)  
    00401A52 83 C4 10             add         esp,10h
    So I changed my __asm block accordingly and finally got it to work. This is what I have now:

    Code:
    #include "stdafx.h"
    
    #include <iostream>
    
    #include <tchar.h>
    #include <Windows.h>
    
    // MessageBox() function needs user32.lib to be added to the link dependancies
    
    using namespace System;
    
    
    #pragma managed(push,off)
    
    const _TCHAR achMessage[]=_T("Hello world!");
    
    void TwilightZone()
    {
      std::cout << "Boo!" << std::endl;
      __asm {
        xor   eax,eax
        push  eax
        push  eax
        push  offset achMessage
        push  eax
        call  dword ptr [MessageBox]
        add   esp,10h  // This line is new for the C++/CLI environment!
      }
    }
    
    #pragma managed(pop)
    
    int main(array<System::String ^> ^args)
    {
      TwilightZone();
      Console::WriteLine("Back to reality!");
      Console::ReadLine();
      return 0;
    }
    Apparently, and for (at least to me) obscure reasons, the native code inside the C++/CLI project calls a __cdecl version of the API function instead of the usual __stdcall version. But at least I now hacked it until it works. Hopefully, you can pull some conclusions out of that, too, that would help you. The CLR support in that project, BTW, was set to /clr, not /clr:pure or even /clr:safe of course, which I wouldn't suppose to compile that mixed code at all.

    Ah, and BTW again, I found something on MSDN about which registers to preserve in __asm blocks. You have much more freedom in using registers than I supposed to, partially because the compiler is aware of which registers you used in your __asm block when generating the code outside that block.
    Last edited by Eri523; August 21st, 2010 at 10:04 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured