gcc asm错误消息:'(% rax,% edx,4)'不是有效的基/索引表达式

moiiocjp  于 2022-11-13  发布在  其他
关注(0)|答案(3)|浏览(228)

:96:错误:'(% rax,% edx,4)'不是有效的基/索引表达式
第97行:错误:ウ-4(% rax,% edx,4)Ж不是有效的基/索引表达式。
第101行:错误:'(% rax,% edx,4)'不是有效的基/索引表达式
第102行:错误:ウ-4(% rax,% edx,4)Ж不是有效的基/索引表达式。
我收到这些错误消息,但不确定如何修复。
这是我的代码:

__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"

一些帮助解释如何修复这些错误信息,请。我试图使一个泡沫排序在ASM。

k5ifujac

k5ifujac1#

您没有说您的目标处理器,但它似乎是x64。在x64上,(%rax, %edx, 4)不是法律的的组合。请查阅处理器手册以获得有效寻址模式的列表。我猜您的目标是(%rax, %rdx, 4)

9rbhqvlz

9rbhqvlz2#

问题的最可能原因是在%3操作数中使用了显式32位整数类型。您没有显示内联程序集的约束列表。但如果您显示了,则会出现上述情况:

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;
}

在32位模式下编译该代码可以正常工作:

$ 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

但在64位模式下,编译器/汇编器并不喜欢这样:

$ 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

解决这个问题的方法是使用#include <stdint.h>并将最终用于寻址的寄存器操作数(作为基址或变址寄存器)转换为uintptr_t(这是一种整数数据类型,保证与指针“大小兼容”,无论您使用的是32位还是64位)。通过这种更改,64位编译成功并创建以下输出:

$ 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

祝您的内联程序集“与32/64位无关”!

y4ekin9u

y4ekin9u3#

我在一个简单的数组求和中也遇到了同样的问题,在使用了@FrankH.的建议后,(欢呼@FrankH.)
这是我为gcc编写的内联asm代码

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);
}

相关问题