我正在尝试为AVR编写自定义内存复制函数作为内联汇编,因为avr-gcc将始终使用循环进行memcpy和struct赋值,这在时间上是低效的。我想使用内存操作数来避免添加“内存”clobber。我目前有这个:
void copy_2_bytes (char *restrict dst, char *restrict src)
{
struct S {
char x[2];
};
__asm__(
" ld __tmp_reg__,%[src]+\n"
" st %[dst]+,__tmp_reg__\n"
" ld __tmp_reg__,%[src]+\n"
" st %[dst]+,__tmp_reg__\n"
: [dst] "=m" ( *(struct S *)dst )
: [src] "m" ( *(struct S *)src )
);
}
这是编译,但一般来说它是不正确的,因为它修改了与内存操作数对应的指针寄存器对。很容易看出gcc假设寄存器保持不变,例如通过添加“* dst = 0;”集会后。
另一方面,Y和Z寄存器支持“ldd”和“std”指令,这些指令也采用立即偏移,因此它们可用于访问多个字节而无需修改。但是,似乎没有办法迫使gcc不选择X寄存器,这不支持。
更新
实际上,如果gcc确定内存操作数的地址是常量,它会将常量地址传递给程序集,而不是寄存器对。所以现在,我完全不知道如何处理这个问题。是否有一些魔术指令或汇编宏可以同时处理指针寄存器和常量地址?