汇编 - 内联asm - 从一个数组复制到另一个数组?

Lar*_*rry 5 linux assembly x86-64 cpu-registers att

背景:

Linux 64. AT&T.

GCC 4.8.2(-O3 -march = native)

左手下方的x86_64 abi,​​在第21页打开.

预期的C代码:

为了明确意图,这里有一个想法:

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

有缺陷的C代码:

检测到错误:

Error: `(%rsp,%esi,4)' is not a valid base/index expression
Run Code Online (Sandbox Code Playgroud)

代码 :

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

汇编代码(问题背后的线条):

...
start_loop:
movl (%rsp,%edx,4), (%si,%edx,4)
addl $1, %edx
cmp $4, %edx
jne start_loop
...
Run Code Online (Sandbox Code Playgroud)

问题:

我该如何表达正确的代码?我哪弄错了?

谢谢

更新:

将装配线更改为时

movl (%rsp,%rdx,4), (%rsi,%rdx,4)

我明白了

Error: too many memory references for 'mov'

什么 ??

更新2

对于读者来说,似乎我的系统非常特殊,因为它不会放置正确的指令大小.

我必须手动输入我的变量int64_t 作为一个例子来强制r*x的事情发生.如果c11/c ++ 11使用uintptr_t类型.

否则,gcc会粘贴32位版本,导致无效的基本/索引错误.

它多次咬我.我希望现在不适合你.

Jes*_*ter 5

现在关闭ABI文档,并打开intel手册,基本架构和指令集参考当然: - >

首先,mov不接受两个内存操作数,你必须通过一个寄存器或使用专门的字符串移动movs.其次,在有效地址中,您不能混合使用16位,32位和64位寄存器.鉴于代码片段中的类型,编译器为您替换16位寄存器是非常可疑的.此外,由于不可能的约束,它甚至不应该编译,res作为一个你不能用它作为输出的数组.此外,您正在更改counter变量,但您没有告诉编译器.

gcc内联汇编是一件非常复杂的事情.如果可能的话,最好避免使用它,特别是如果你是初学者,否则你将与编译器对抗而不是学习汇编.

固定版本可能如下所示:

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