none
Error: '__asm' keyword not supported on this architecture

    Question

  • Dear All,
    I am proting a project from VS2003 and OS running was Windows 2003 Server 32 bit  to Vs2010 in Window 2008 Server 64bit.

    I have set of code snippets in my code.

    __asm
        {
            mov eax, dword ptr [ebp + 0x4]
            mov dword ptr [memoryAllocator], eax
        }


    When I try to compile it in Vs2010 I get the following error.

    nonstandard extension used : '__asm' keyword not supported on this architecture


    What would be the workaround for this and equivalent code in VS2010?

    Many thanks in advance.
    -R
    Wednesday, March 24, 2010 4:22 PM

Answers

  • Also consider this:

     

      #include <intrin.h>

     

      void * memoryAllocator = _ReturnAddress();

     

    • Proposed as answer by Eric Haddan Friday, March 26, 2010 2:50 PM
    • Marked as answer by rajukgp Saturday, March 27, 2010 3:35 AM
    Friday, March 26, 2010 7:28 AM

All replies

  • The __asm keyword is not supported on x64 architectures. The two work arounds are to either use an assembler and call the function written in assembly or use the compiler intrinsics.

    The question is, what are you trying to do? Besides the fact that assembly is not portable, and that asm snippet would most likely cause huge problems on an x64 system (for example, if that is getting a memory address, you just truncated it, also the x64 doesn't work relative to rbp any more, it is relative to rsp). It would be benificial to understand what you are trying to do with that code to give a proper answer.


    Visit my (not very good) blog at http://c2kblog.blogspot.com/
    Wednesday, March 24, 2010 4:33 PM
  • I agree heartily with crescens2k. The workaround is to not use assembler at all. Do it (whatever "it" is) in C++.
    Wednesday, March 24, 2010 4:40 PM
  • As crescens2k and Brian said, you cannot use the __asm keyword anymore.

    Judging by the assembly code provided, you are probably trying to get the return address in your function.  You might want to try StackWalk64 to get that kind of information.

    • Proposed as answer by Eric Haddan Wednesday, March 24, 2010 8:43 PM
    Wednesday, March 24, 2010 8:42 PM
  • Dear All,

    Thanks for all sugesionts and help.Due to lack of documentation I am not sure as what the function below where the above code snippet is used for.I am attaching the code below, it looks like the assembler is called for tracking memory in a memory allocation function.

     

    MeanwhileI have commented the assembler part in case of x64 and able to build the project.But not sure what would impact.

    The below AllocateMemoryInternal() function doesn't contain any assembler part it is only C++.Should I go ahead with commenting or try to use Intrinsics?

     

    MEM_DLLEXPORT void *AllocateMemory( long bytes )
    {
    void* memoryAllocator = NULL;

     
        // This bit of code picks up the return address off the stack frame so
        // that we can track who is allocating memory
        __asm
        {
            mov eax, dword ptr [ebp + 0x4]
            mov dword ptr [memoryAllocator], eax
        }
        return ( AllocateMemoryInternal( bytes, memoryAllocator, kMemUtilAllocateNormal ) );
    }









    MEM_DLLEXPORT void *AllocateMemoryInternal( long bytes, void* memoryAllocator, uint32 type )
    {
        long            totalBytes;
        MemoryHeader    *mems;
        void            *userMems;

        ASSERT( bytes >= 0 );
        ASSERT( bytes < kMaxReasonableMemorySize );
       
    #if defined(MEM_DEBUG)

        //REQID: SERVER MEMORY TRACKING
        //An Issue : The use of C style synchromization API can cause deadlock in Multithreaded usage.
        //If this function throws an exception, the critical section wont be released
        //Hopefully this should not create problem if this exception is not caught to continue
        //the normal execution path for other threads.
        //Should use CSingleLock( )or else this block should be protected with try-catch
        GrabMemUtilMutex();
       
        if ( bytes > gMemoryMaxBlockSize )
        {
            gMemoryMaxBlockSize = bytes;
        }
    #endif // MEM_DEBUG
       
        totalBytes = bytes + sizeof( MemoryHeader ) + kTailFillSize;

        mems = (MemoryHeader *) FCSMalloc( (size_t)totalBytes );

        if ( mems )
        {
            GarbageFill( mems, totalBytes, kGarbageValue );

    #if defined(MEM_DEBUG)
            // Update stats
            gMemoryTotalAllocations++;
            gMemoryCurrentAllocations++;
            if ( gMemoryCurrentAllocations > gMemoryMaxAllocations )
            {
                gMemoryMaxAllocations = gMemoryCurrentAllocations;
            }
            gMemoryTotalBytesAllocated += bytes;
            gMemoryCurrentBytesAllocated += bytes;
            if ( gMemoryCurrentBytesAllocated > gMemoryMaxBytesAllocated )
            {
                gMemoryMaxBytesAllocated = gMemoryCurrentBytesAllocated;
            }
            if ( gMemoryTotalAllocations == gMemoryBreakAtAllocation )
            {
    #if defined(_WIN32)
                DebugBreak();
    #endif
            }
    #endif // MEM_DEBUG

            mems->size = bytes;
            mems->type = type;
            userMems = (void *) ( mems + 1 );

            CreateBlockSignature( mems );

    #if defined(MEM_LEAK_INFO)       
            AddBlockToLeakList( mems, gMemoryTotalAllocations, memoryAllocator );
    #endif // MEM_LEAK_INFO

            // We better have an OK memory block before we return, otherwise we'll
            // falsely accuse the caller of hosing memory somehow.
            ASSERT( ValidMemoryBlock( userMems ) );
        }
        else
        {
            WARNINGMESSAGE( "FCSMalloc failed" );
            MEM_FCTRIGGER( "FCSMalloc failed" );
            userMems = (void *) NULL;

    #if defined(MEM_DEBUG)
            gMemoryFailedAllocations++;
    #endif // MEM_DEBUG
        }

    #if defined( SERVER_MEM_DEBUG )
    //>>>
        //REQID: SERVER MEMORY TRACKING
        //>>
        //Server memory block module
        //If allocations done are in mod of SERVER_MEMTRAC_INTRVL
        //Dump memory statistic
        //Take new snapshot of the memory module variables
        if( gEnable_IntervalMemoryTracking )
        {
            //If module is enabled
            if( gMemoryTotalAllocations % gInterval_MemoryAllocations == 0 )
            {
                //Print statistic & mem dump
                MemTrack_PrintMemoryDiffStatistics( );
                //save the present state
                MemTrack_TakeMemorySnapshot( );
            }
        }
    //>>
    #endif

    #if defined(MEM_DEBUG)
        ReleaseMemUtilMutex();
    #endif // MEM_DEBUG

        return ( userMems );
    }

     

    Thanks

    -R

    Thursday, March 25, 2010 3:18 AM
  • Well, as Eric said quite rightly is to use StackWalk64, after the first call the stack frame will have the return address. The other option you have is to write this function purely in assembly. This is harder and I really would suggest you go for StackWalk64.
    Visit my (not very good) blog at http://c2kblog.blogspot.com/
    Thursday, March 25, 2010 4:59 PM
  • Will surely try StackWalk64.Thanks for all help.Curious to know, what if I use  one of the appropriate intrinsics like __movsb, __movsd, __movsq or __movsw
    replacing   "mov" in below.

     mov eax, dword ptr [ebp + 0x4]
      mov dword ptr [memoryAllocator], eax.


    I am not sure if my query is absurd.Please suggest.
    Thanks
    -R


    Friday, March 26, 2010 7:16 AM
  • Also consider this:

     

      #include <intrin.h>

     

      void * memoryAllocator = _ReturnAddress();

     

    • Proposed as answer by Eric Haddan Friday, March 26, 2010 2:50 PM
    • Marked as answer by rajukgp Saturday, March 27, 2010 3:35 AM
    Friday, March 26, 2010 7:28 AM
  • Thanks for the info.Looks to be much simpler approach. Where can I get sample programs for calling StackWalk64 function.I tried googling but not getting the correct sample programs ?

    -R

    Friday, March 26, 2010 9:51 AM
  • Wow, that's a good one Viorel_!

    rajukgp, you should be able to just use the line that he provided to replace all of your assembly in that function.

    Friday, March 26, 2010 2:50 PM
  • Excellent!! _ReturnAddress(); works perfectly. Thanks for all help.

    -R

    Saturday, March 27, 2010 3:36 AM