What does the GCC error message, "Error: unsupported for `mov'", mean?

24,496

Solution 1

You are attempting to compile 32-bit assembly code on a 64-bit machine. The inline assembly you list compiles to:

movl -24(%rbp), %ebx
movl %rsi, %ecx       <--- error here
movl -28(%rbp), %edx
movl $103, %eax
int $128
movl %eax, %r12d

As you can see, you're attempting to store a 64-bit register in a 32-bit register, which is illegal. More importantly, this isn't the 64-bit ABI system call protocol either.

Try compiling with -m32 to force 32-bit ABI.

Solution 2

you should use "movq" to move 64 bits value.

see like this:

int main(void) 
{
  long str_len = 15;
  const char* str = "hello world!\n\r";

asm volatile(
    "movl $4, %%eax\n\t"
    "movl $1, %%ebx\n\t"
    "movq %0, %%rcx\n\t"
    "movq %1, %%rdx\n\t"
    "int      $0x80\n\t"
    :       
    :"r"(str), "r"(str_len)
    :"eax","ebx", "rcx", "rdx"
);
return 0;

}

Share:
24,496
Dan
Author by

Dan

Updated on July 09, 2022

Comments

  • Dan
    Dan almost 2 years

    I am just trying to compile some simple example code I typed in from a book, and GCC gives me the above error. Here's my code:

    $ cat -n test.cpp
    
     1  #define READ_COMMAND    3
     2  
     3  #define MSG_LENGTH  128
     4  
     5  #include <stdlib.h>
     6  #include <stdio.h>
     7  
     8  int main(int argc, char *arg[])
     9  {
    10      int syslog_command = READ_COMMAND;
    11      int bytes_to_read = MSG_LENGTH;
    12      int retval;
    13      char buffer[MSG_LENGTH];
    14  
    15      asm volatile(
    16          "movl %1, %%ebx\n\t"
    17          "movl %2, %%ecx\n\t"
    18          "movl %3, %%edx\n\t"
    19          "movl $103, %%eax\n\t"
    20          "int $128\n\t"
    21          "movl %%eax, %0"
    22          :"=r" (retval)
    23          :"m"(syslog_command),"r"(buffer),"m"(bytes_to_read)
    24          :"%eax","%ebx","%ecx","%edx");
    25      if (retval > 0) printf("%s\n", buffer);
    26  
    27  }
    28  
    29  
    

    The code is supposed to invoke the syslog() system call to read the last 128 bytes from the kernel printk() ring buffer. Here is some information about my OS and system configuration:

    uname -a:

    Linux 3.2.0-26-generic #41-Ubuntu SMP Thu Jun 14 17:49:24 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux

    gcc -v:

    Using built-in specs.
    COLLECT_GCC=gcc
    COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.6/lto-wrapper
    Target: x86_64-linux-gnu
    

    Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.6.3-1ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu

    Thread model: posix
    
    gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) 
    

    Heres the full error:

    $ gcc test.cpp
    
    test.cpp: Assembler messages:
    
    test.cpp:25: Error: unsupported for `mov'
    
  • Peter Cordes
    Peter Cordes over 2 years
    Yes, that would get it to compile, but note that it's pointless to use 64-bit registers for int 0x80; the 32-bit system call is only going to look at the 32-bit register. (What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?). So you could do mov %k0, %%ecx to force it to print the 32-bit register name when expanding %0, instead of whatever width it picked based on the C var.
  • Peter Cordes
    Peter Cordes over 2 years
    Or better, use a "c"(str) constraint to ask for the pointer in ECX/RCX in the first place, so you don't need any mov, just asm("int $0x80" : "=a"(retval) : ... ) as the template with no clobbers needed, not forcing the compiler to find different registers for the inputs.
  • Peter Cordes
    Peter Cordes over 2 years
    Also note that the key thing was using a 64-bit destination register, not just the movq mnemonic. You could use plain mov and let the assembler infer the operand-size. So yes, this does answer the question about mov sizes, but for a system call wrapper this is the worst possible way to go about it, and basically wrong to use int 0x80 instead of syscall for 64-bit code. Hopefully useful to people using mov for other reasons, though.
  • Peter Cordes
    Peter Cordes over 2 years
    Also, Linux uses just \n for newline, not DOS \r\n, and certainly not \n\r (used nowhere).