Linux 64. AT&T.
GCC 4.8.2 (with -O3 -march=native)
The x86_64 abi under my left hand, opened at page 21.
So that the intent is made clear, here is the idea :
int32_t res[] = {0,0,0,0};
int32_t primo[] = {5,8,50,150};
for (int32_t x = 0; x < 4; ++x) {
res[x] = primo[x];
}
printf("%d %d %d %d\n", res[0], res[1], res[2], res[3]);
Error detected :
Error: `(%rsp,%esi,4)' is not a valid base/index expression
The code :
int32_t res[] = {0,0,0,0};
int32_t primo[] = {5,8,50,150};
int32_t counter = 0;
__asm__ volatile(
"start_loop:\n\t"
"movl (%1,%2,4), (%0,%2,4)\n\t"
"addl $1, %2\n\t"
"cmp $4, %2\n\t"
"jne start_loop"
: "=&r"(res)
: "r"(primo),"r"(counter)
:"cc"
);
printf("%d %d %d %d\n", res[0], res[1], res[2], res[3]);
...
start_loop:
movl (%rsp,%edx,4), (%si,%edx,4)
addl $1, %edx
cmp $4, %edx
jne start_loop
...
How can I express the right code ? Where did I got it wrong ?
Thanks
when changing the assembly line to
movl (%rsp,%rdx,4), (%rsi,%rdx,4)
I get
Error: too many memory references for 'mov'
What ??
For the readers, it seems that my system is quite special in that it will not put the right instruction size.
I have to manually type my variables with int64_t
as an example to force the r*x thing to happen. If c11/c++11 use uintptr_t
type.
Otherwise, gcc sticks with the 32 bits version which causes invalid base/index error.
It has bitten me multiple times. I hope it won't for you now.
Now close the ABI doc, and open the intel manual, basic architecture and the instruction set reference of course :->
First of all, mov
does not accept two memory operands, you have to go through a register or use the specialized string move movs
. Second, in the effective address you can not mix 16, 32 and 64 bit registers. Given the types in your code fragment, it is highly suspicious that the compiler substituted 16 bit registers for you. Also, it shouldn't even compile due to impossible constraints, res
being an array you can't use it as output. Furthermore you are changing the counter
variable, but you don't tell the compiler that.
gcc inline assembly is a very complicated thing. Better avoid it if possible, especially if you are a beginner or else you will be fighting the compiler instead of learning assembly.
A fixed version may look like:
#include <stdint.h>
#include <stdio.h>
int main()
{
int32_t res[] = {0,0,0,0};
int32_t primo[] = {5,8,50,150};
int32_t counter = 0;
int32_t tmp;
__asm__ volatile(
"start_loop:\n\t"
"movl (%3, %q1, 4), %0\n\t"
"movl %0, (%2, %q1, 4)\n\t"
"addl $1, %1\n\t"
"cmp $4, %1\n\t"
"jne start_loop"
: "=&r" (tmp), "+r" (counter)
: "r" (res), "r"(primo)
: "cc", "memory"
);
printf("%d %d %d %d\n", res[0], res[1], res[2], res[3]);
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With