gpt4 book ai didi

c - gcc : ‘asm’ operand has impossible constraints 中的扩展 asm

转载 作者:太空狗 更新时间:2023-10-29 15:35:37 32 4
gpt4 key购买 nike

这个“strcpy”函数的目的是将src的内容复制到dest,结果很好:显示两行“Hello_src”。

#include <stdio.h>

static inline char * strcpy(char * dest,const char *src)
{
int d0, d1, d2;
__asm__ __volatile__("1:\tlodsb\n\t"
"stosb\n\t"
"testb %%al,%%al\n\t"
"jne 1b"
: "=&S" (d0), "=&D" (d1), "=&a" (d2)
: "0"(src),"1"(dest)
: "memory");
return dest;
}

int main(void) {
char src_main[] = "Hello_src";
char dest_main[] = "Hello_des";
strcpy(dest_main, src_main);
puts(src_main);
puts(dest_main);
return 0;
}
  1. 我尝试将行 : "0"(src),"1"(dest) 更改为 : "S"(src),"D"(dest ),发生错误:'asm' 操作数具有不可能的约束。我就是无法理解。我认为这里的“0”/“1”指定了与第0/1个输出变量相同的约束。第 0 个输出的约束是 =&S,第 1 个输出的约束是 =&D。如果我改成0-->S,1-->D,应该不会有错。这是怎么回事?

  2. “clobbered registers”或 earlyclobber 操作数 (&) 有什么用吗?我尝试去掉“&”或“memory”,这两种情况的结果都和原来的一样:输出两行“Hello_src”字符串。那么我为什么要使用“破坏”的东西呢?

最佳答案

earlyclobber & 意味着特定的输出是在输入被消耗之前写入的。因此,编译器可能不会将任何输入分配给同一寄存器。显然,使用 0/1 样式会覆盖该行为。

当然,clobber 列表也有重要的用途。编译器不解析您的汇编代码。它需要 clobber 列表来确定您的代码将修改哪些寄存器。你最好不要说谎,否则可能会出现细微的错误。如果你想看到它的效果,请尝试欺骗编译器在你的 asm block 周围使用寄存器:

extern int foo();
int bar()
{
int x = foo();
asm("nop" ::: "eax");
return x;
}

生成的汇编代码相关部分:

call    foo
movl %eax, %edx
nop
movl %edx, %eax

注意编译器如何必须将 foo 的返回值保存到 edx 中,因为它相信 eax 将被修改。通常它会把它留在 eax 中,因为那是以后需要它的地方。在这里你可以想象如果你的 asm 代码在没有告诉编译器的情况下修改了 eax 会发生什么:返回值将被覆盖。

关于c - gcc : ‘asm’ operand has impossible constraints 中的扩展 asm,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26191261/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com