1

:96: Error: `(%rax,%edx,4)' is not a valid base/index expression

line97: Error: `-4(%rax,%edx,4)' is not a valid base/index expression

line101: Error: `(%rax,%edx,4)' is not a valid base/index expression

line102: Error: `-4(%rax,%edx,4)' is not a valid base/index expression

I get these error messages and am not sure how to fix it.

This is my code:

   

__asm__ (

           "loop:       \n\t"
           "movl        $1,%3\n\t"
           "movl        $0, %6\n"

           "start:        \n\t"

           "movl        (%1,%3,4),%4\n\t"       
           "movl        -4(%1, %3, 4), %5\n\t"

           "cmpl        %4, %5\n\t"           
           "jle         next\n\t"

           "xchgl        %4, %5\n\t"               
           "movl        %4, (%1, %3, 4)\n\t"        
           "movl        %5, -4(%1, %3, 4)\n\t"        
           "movl        $1, %6\n\t"

           "next:       \n\t"
           "incl        %3  \n\t"        

           "cmpl        %3, %2\n\t"
           "jge        start\n\t"        

           "cmpl        $0, %6\n\t"
           "je        end\n\t"

           "jmp        loop\n\t"        
           "end:        \n\t"

Some help explaining how to fix these error message, please. I am trying to make a bubble sort in ASM.

Unheilig
  • 16,196
  • 193
  • 68
  • 98
user1055916
  • 57
  • 3
  • 6

3 Answers3

6

You didn't say what processor you are targeting, but it appears to be x64. On x64, (%rax, %edx, 4) is not a legal combination. Consult the processor manual for a list of valid addressing modes. My guess is that you meant (%rax, %rdx, 4).

Raymond Chen
  • 44,448
  • 11
  • 96
  • 135
5

Most likely cause of your problem is the use of an explicit 32bit integer type in the %3 operand. You haven't shown the constraints list for your inline assembly. But the above occurs if you do:

int main(int argc, char **argv)
{
    int result, foobaridx;

    foobaridx = foobar[4];

    __asm__ (
        "       dec    %2\n\t"
        "       movl   (%1, %2, 4), %0\n\t"
    : "=r"(result) : "r"(foobar), "r"(foobaridx) : "memory", "cc");

    return result;
}

Compiling this in 32bit mode works alright:

$ gcc -O8 -m32 -c tt.c
$ objdump -d tt.o

tt.o:     file format elf32-i386

00000000 :
   0:   55                      push   %ebp
   1:   b8 00 00 00 00          mov    $0x0,%eax
   6:   89 e5                   mov    %esp,%ebp
   8:   83 ec 08                sub    $0x8,%esp
   b:   8b 15 10 00 00 00       mov    0x10,%edx
  11:   83 e4 f0                and    $0xfffffff0,%esp
  14:   4a                      dec    %edx
  15:   8b 04 90                mov    (%eax,%edx,4),%eax
  18:   83 ec 10                sub    $0x10,%esp
  1b:   c9                      leave
  1c:   c3                      ret

But in 64bit mode, the compiler/assembler doesn't like it:

$ gcc -O8 -c tt.c
/tmp/cckylXxC.s: Assembler messages:
/tmp/cckylXxC.s:12: Error: `(%rax,%edx,4)' is not a valid base/index expression

The way to fix this is to use #include <stdint.h> and cast register operands that'll end up being used for in addressing (as base or index registers) to uintptr_t (which is an integer data type guaranteed to be 'size-compatible' to pointers, no matter whether you're on 32bit or 64bit). With that change, the 64bit compile succeeds and creates the following output:

$ gcc -O8 -c tt.c
$ objdump -d tt.o

tt.o:     file format elf64-x86-64

Disassembly of section .text:

0000000000000000 :
   0:   48 63 15 00 00 00 00    movslq 0(%rip),%rdx        # 7 
   7:   b8 00 00 00 00          mov    $0x0,%eax
   c:   48 ff ca                dec    %rdx
   f:   8b 04 90                mov    (%rax,%rdx,4),%eax
  12:   c3                      retq

Good luck making your inline assembly "32/64bit agnostic" !

FrankH.
  • 17,675
  • 3
  • 44
  • 63
1

I also had the same issue in a simple array sum, and after using @FrankH. 's advice, (cheers @FrankH.)

it works. here is my inline asm code for gcc

inline int array_sum(const int *value, const int &size) {

  int sum = 0;

  // for (int i = 0; i < size; i++) {
  //   sum = sum + value[i];
  // }

  for (int i = 0; i < size; i++)
    asm("addl (%1,%2,4),%0"
        : "=r"(sum)
        : "r"((uintptr_t)value), "r"((uintptr_t)i), "0"(sum)
        : "cc");
  return (sum);
}
  • as the issue is with (%rdx,%eax,4), the index (namely i), %eax is the cause of this problem, so just by using long instead in for i would alsd sort the problem, and there wont be any need to casting too auto can aldo be used if using cpp instead of c – zafar hussain Sep 27 '22 at 14:09
  • You can simply by using `"+r"(sum)` (an input/output operand) instead of a separate `"0"(sum)` input. A matching constraint is primarily useful if you want a different C variable to hold the input than the output. e.g. for a system call, `"=a"(retval) : "a"(__NR_write), other operands` where the input is a constant. – Peter Cordes Sep 28 '22 at 06:17