dcsimg
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8

Thread: ASM and x64

  1. #1
    Join Date
    Oct 2002
    Location
    Timisoara, Romania
    Posts
    14,360

    ASM and x64

    Does anyone know how to port this to x64, because inline asm is no longer supported?

    Code:
          __declspec( naked ) DWORD_PTR* GetEip()
          {
             __asm {
                pop   eax         ; retrieves return adress
                push  eax         ; restores return adress
                ret
             }
          }
          
          __declspec( naked ) DWORD_PTR* GetEbp()
          {
             __asm {
                mov   eax, ebp
                ret
             }
          }
    Thank you.
    Last edited by cilu; July 19th, 2010 at 06:17 AM.
    Marius Bancila
    Home Page
    My CodeGuru articles

    I do not offer technical support via PM or e-mail. Please use vbBulletin codes.

  2. #2
    Join Date
    Mar 2006
    Posts
    149

    Re: ASM and x64

    ...inline asm is no longer supported...
    I hadn't heard that. It's awful. Is it just temporary or is inline ASM support to be permanently dropped? It's an indespensible tool for debugging release builds.

    ...how to port this to x64...
    The first function in particular seems quite compiler dependent. Is this for a device driver?

    This version of GetEip() seems to work, though it has pesky runtime check failure in a debug build.

    This GetEbp() does not work, at least on my machine. It fails on the mov instruction with an access violation, I think because it is trying to execute code which is not in the code page. If you can get past that, I'm expecting it to still have a problem because the return address is not pushed onto the stack, but I think that is the more minor problem.

    Code:
    DWORD_PTR * GetEip(void)
    {
        void const * const p            = NULL;  // Must come first. Compiler dependent.
        int  const         nPointerSize = sizeof(p);
    #   ifdef _DEBUG
        int  const         nGuardBytes  = 8;
    #   else
        int  const         nGuardBytes  = 0;
    #   endif
    
    #   pragma warning(push)
    #   pragma warning(disable:4700) // Use of uninitialized local variable
        _ASSERT(nPointerSize == 4 || nPointerSize == 8);
        if (nPointerSize == 4)
            return *reinterpret_cast<DWORD_PTR **>((int    ) &p + nPointerSize + nGuardBytes);
        else
            return *reinterpret_cast<DWORD_PTR **>((__int64) &p + nPointerSize + nGuardBytes);
    #   pragma warning(pop)
    }
    
    unsigned char static const byGetEbpCode[] = { 0x8B, 0xC5, 0xC3, 0x5F, 0x5E };
    DWORD_PTR * (__stdcall * const GetEbp)(void)
        = reinterpret_cast<DWORD_PTR * (__stdcall * const)(void)>(&byGetEbpCode);
    
    int main(int argc,char* argv[])
    {
        DWORD_PTR * eip = GetEip();
        DWORD_PTR * ebp = GetEbp();
    
        return 0;
    }

  3. #3
    Join Date
    Oct 2002
    Location
    Timisoara, Romania
    Posts
    14,360

    Re: ASM and x64

    I hadn't heard that. It's awful. Is it just temporary or is inline ASM support to be permanently dropped? It's an indespensible tool for debugging release builds.
    Here it is: http://msdn.microsoft.com/en-us/library/hb5z4sxd.aspx. Nothing temporary, at least not as far as I know. The only way to use assembly code in a VC++ project is to put the code in a separate file are use ml64.exe to link it, or use compiler intrinsics.

    The first function in particular seems quite compiler dependent. Is this for a device driver?
    No, it's for walking the call stack. Not very familiar with it, it's part of a big project. I'm trying to see what it takes to migrate it on x64, and this was the first thing that generated errors. Looking on the web, I actually saw different versions of those methods.
    Code:
    unsigned long static __fastcall GetEIP()
    {
    	volatile unsigned long eip_value;
    	__asm	mov eax, [ebp+4]
    	__asm	mov dword ptr [eip_value], eax
    
    	return eip_value;
    }
    Can you explain what these magic numbers are?
    Code:
    { 0x8B, 0xC5, 0xC3, 0x5F, 0x5E };
    I think another way to put this
    Code:
        if (nPointerSize == 4)
            return *reinterpret_cast<DWORD_PTR **>((int    ) &p + nPointerSize + nGuardBytes);
        else
            return *reinterpret_cast<DWORD_PTR **>((__int64) &p + nPointerSize + nGuardBytes);
    is
    Code:
    return *reinterpret_cast<DWORD_PTR **>((DWORD_PTR) &p + nPointerSize + nGuardBytes);
    Because DWORD_PTR is 4 bytes (like int) on 32-bit, and 8 bytes (like __int64) on 64 bit.

    And probably could replace nPointerSize with sizeof(DWORD_PTR).
    Code:
    return *reinterpret_cast<DWORD_PTR **>((DWORD_PTR) &p + sizeof(DWORD_PTR) + nGuardBytes);
    Marius Bancila
    Home Page
    My CodeGuru articles

    I do not offer technical support via PM or e-mail. Please use vbBulletin codes.

  4. #4
    Join Date
    Mar 2006
    Posts
    149

    Re: ASM and x64

    Can you explain what these magic numbers are?
    That's the code for

    Code:
            mov   eax, ebp
            ret
    The disassembly window verifies that as the correct byte sequence, but my machine consistently generates a GP Fault when the execution pointer tries to execute the move instruction. Likewise, another approach I tried also faulted when it attempted to memcpy that byte sequence to the start of a function. I don't know very much about the x86 architecture but assume these faults are rooted in some distinction between code and data segments.

    If you could overcome the GP fault, for x64 you would probably want to use whatever byte sequence corresponds to

    Code:
            mov   rax, rbp
            ret
    or so I assume. (?)

    I think another way to put this... ...is...
    Nice simplification. Wish I'd noticed it.
    Also nGuardBytes should probably be a static const to get it off the stack frame.

  5. #5
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,599

    Re: ASM and x64

    VC should be still supporting this MS Specific:
    Code:
    extern "C" void* _ReturnAddress();
    Best regards,
    Igor

  6. #6
    Join Date
    Oct 2002
    Location
    Timisoara, Romania
    Posts
    14,360

    Re: ASM and x64

    Yes, that intrinsic is still supported.
    Marius Bancila
    Home Page
    My CodeGuru articles

    I do not offer technical support via PM or e-mail. Please use vbBulletin codes.

  7. #7
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,599

    Re: ASM and x64

    And is it what you looked for?
    Best regards,
    Igor

  8. #8
    Join Date
    Oct 2002
    Location
    Timisoara, Romania
    Posts
    14,360

    Re: ASM and x64

    Eventually I fixed this with RtlCaptureContext (because I only need to support WinXP and newer OS). I have something like this:
    Code:
       CONTEXT context;
       RtlCaptureContext(&context);
    
    #ifdef _WIN64
       // x64 uses only Rsp, Rbp is not used 
       DWORD_PTR* pFrame= (DWORD_PTR*)context.Rsp;
    #else
       // x86 uses Ebp
       DWORD_PTR* pFrame = (DWORD_PTR*)context.Ebp;
    #endif
    This is good enough at least for now.

    However, for an better stack walk, one should use StackWalk64 (works with x86, x64 and IA64). http://msdn.microsoft.com/en-us/libr...8VS.85%29.aspx Here is an article on how to implement a stack walker: http://www.codeproject.com/KB/threads/StackWalker.aspx.
    Marius Bancila
    Home Page
    My CodeGuru articles

    I do not offer technical support via PM or e-mail. Please use vbBulletin codes.

Posting Permissions

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


Windows Mobile Development Center


Click Here to Expand Forum to Full Width




On-Demand Webinars (sponsored)