1
votes

In my previous topic: How to read registers: RAX, RBX, RCX, RDX, RSP. RBP, RSI, RDI in C or C++? I asked about reading those registers. Now I wrote a code to read (just for now on) RAX and RBX.

I'm using CodeBlocks pm 64-bit Windows 7 with MinGW as a compiler and I'm working on an x86-64 CPU. When I tried to compile the below code, I got those errors:

Error: bad register name `%rax'
Error: bad register name `%rbx'

And the code:

#include <iostream>
#include <cstdlib>
#include <stdint.h>

void read(void)
{
    uint64_t rax = 0, rbx = 0;
    __asm__ __volatile__ (
        /* read value from rbx into rbx */
        "movq %%rbx, %0;\n"
        /* read value from rax into rax*/
        "movq %%rax, %1;\n"
        /* output args */
        : "=r" (rbx), "=r" (rax)
        : /* no input */
        /* clear both rdx and rax */
        : "%rbx", "%rax"
    );

    /* print out registers content */
    std::cout << "RAX = " << rax << "\n";
    std::cout << "RBX = " << rbx << "\n";

}

int main(int argc, char **argv)
{
    read();

    return 0;
}
2
You are compiling 32 bit code I expectDavid Heffernan

2 Answers

4
votes

I suspect your error comes from the "clobber" line:

    : "%rbx", "%rax"

which should read:

    : "rbx", "rax"

(Oh, and don't ask me why!)

Edit: You will also need to compile for 64-bit, using -m64 or similar - assuming of course the MingW compiler you have is 64-bit capable in the first place.

2
votes

MinGW is a 32-bit compiler. It doesn't support the x86-64 target so you can't use 64-bit registers like RAX. At least that's what happened before at the time of this question. I'm not sure about the situation of mingw right now but for quite a long time it didn't support producing 64-bit binaries. Besides, it's broken in many ways because it uses the ancient MSVCRT runtime library which doesn't support standard C99 printf format specifiers or 80-bit long double. The developers were also reluctant to update, or respond to (pull) requests, therefore mingw-w64 was forked which provided a much more complete solution for Windows. It solved all the printf issues, have more complete support for POSIX and Win32 APIs and many more things that you can read later

If the current version of mingw does support x86-64 then you still need to pass the -m64 option to make it output a 64-bit executable, because mingw is still a 32-bit compiler as I looked over their installer and will compile into 32-bit code by default where RAX is non-existent. See also

But the better way would be moving to better compilers such as mingw-w64, TDM-GCC or Clang which support both 64-bit guest and host natively

In 2005, MinGW-w64 was created by OneVision Software under clean room design principles, since the original MinGW project was not prompt on updating its code base, including the inclusion of several key new APIs and the much needed 64-bit support. In 2008, OneVision then donated the code to Kai Tietz, one of its lead developers, under the condition that it remain open source. It was first submitted to the original MinGW project, but refused under suspicion of using non-public or proprietary information. For many reasons, the lead developer and co-founder of the MinGW-w64 project, Kai Tietz, decided not to attempt further cooperation with MinGW.

MinGW-w64 provides a more complete Win32 API implementation, including:

  • better C99 support
  • better POSIX Threads (pthreads) support (including the possibility to enable C++11 thread-related functionality in GCC's libstdc++)
  • GCC multilib, which allows users to install 32-bit and 64-bit libraries in parallel
  • Unicode entry point (wmain/wWinMain)
  • DDK (from ReactOS)
  • DirectX (from Wine)
  • Large file support
  • Win64 support
  • Some useful tools such as gendef (an improved version of MinGW's pexports utility), and widl (an IDL compiler, a free replacement for MIDL).

https://en.wikipedia.org/wiki/MinGW#MinGW-w64