【问题标题】:extended asm in gcc: ‘asm’ operand has impossible constraintsgcc 中的扩展 asm:“asm”操作数具有不可能的约束
【发布时间】:2014-10-04 08:57:44
【问题描述】:

这个函数“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’ operand has impossible constraints。我只是无法理解。我认为这里的“0”/“1”指定了与第 0/第 1 个输出变量相同的约束。第 0 个输出的约束是 =&amp;S,第 1 个输出的约束是 =&amp;D。如果我改变0-->S,1-->D,应该没有错。怎么回事?

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

【问题讨论】:

  • : "=&amp;S" (d0), "=&amp;D" (d1), "=&amp;a" (d2) 行无效,删除后可以更改“0”和“1”

标签: c gcc assembly


【解决方案1】:

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

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

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 会发生什么:返回值将被覆盖。

【讨论】:

  • 这是否意味着编译器会尝试将每个被破坏的寄存器恢复为其原始值,以确保内联汇编代码不会影响任何寄存器?如果是这样,我只是尝试了另一行:asm ("addl %%ebx, %%eax":::"%eax", "%ebx");,但我发现编译器没有做任何事情来恢复“%eax”或“%ebx”的值。
  • 它只恢复它需要的值的寄存器。它可能只是更改代码生成,以避免使用损坏的寄存器。
  • 谢谢。我得到了它。但是我仍然有些困惑。对于&amp;0/1 操作数,它们对我来说完全相互冲突。 &amp; 告诉输出变量不要使用与输入变量相同的寄存器,但是0/1 告诉输入变量使用与输出变量相同的寄存器。怎么解释?
猜你喜欢
  • 1970-01-01
  • 2014-10-24
  • 1970-01-01
  • 1970-01-01
  • 2018-02-11
  • 2014-04-05
  • 2019-10-26
  • 1970-01-01
相关资源
最近更新 更多