: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"
请帮助解释如何修复这些错误消息。 我试图在ASM中进行冒泡排序。
答案 0 :(得分:6)
您没有说明您要定位的处理器,但它似乎是x64。在x64上,(%rax, %edx, 4)
不是合法组合。有关有效寻址模式的列表,请参阅处理器手册。我猜你的意思是(%rax, %rdx, 4)
。
答案 1 :(得分:3)
最有可能导致问题的原因是在%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 / 64bit不可知”!