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

use*_*916 0 64-bit assembly gcc

:96:错误:`(%rax,%edx,4)'不是有效的基数/索引表达式

line97:错误:`-4(%rax,%edx,4)'不是有效的基本/索引表达式

line101:错误:`(%rax,%edx,4)'不是有效的基数/索引表达式

line102:错误:`-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"
Run Code Online (Sandbox Code Playgroud)

请帮助解释如何修复这些错误消息.我试图在ASM中进行冒泡排序.

Ray*_*hen 6

您没有说明您要定位的处理器,但它似乎是x64.在x64上,(%rax, %edx, 4)不是合法的组合.有关有效寻址模式的列表,请参阅处理器手册.我的猜测是你的意思(%rax, %rdx, 4).


Fra*_*kH. 5

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

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;
}
Run Code Online (Sandbox Code Playgroud)

在 32 位模式下编译它可以正常工作:

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

tt.o:文件格式 elf32-i386

00000000 :
   0: 55 推 %ebp
   1: b8 00 00 00 00 移动 $0x0,%eax
   6: 89 e5 mov %esp,%ebp
   8: 83 ec 08 子 $0x8,%esp
   b: 8b 15 10 00 00 00 移动 0x10,%edx
  11: 83 e4 f0 和 $0xfffffff0,%esp
  14: 12 月 4 日 %edx
  15: 8b 04 90 mov (%eax,%edx,4),%eax
  18: 83 ec 10 子 $0x10,%esp
  1b:c9 离开
  1c:c3 ret

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

$ gcc -O8 -c tt.c
/tmp/cckylXxC.s:汇编器消息:
/tmp/cckylXxC.s:12: 错误: `(%rax,%edx,4)' 不是有效的基/索引表达式

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

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

tt.o:文件格式 elf64-x86-64

.text 节的反汇编:

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

祝您的内联汇编“32/64 位不可知”好运!