Скорее всего, причиной вашей проблемы является использование явного 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;
}
Компиляция в 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-битная независимость"!