Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
gcc中的扩展asm:‘;asm&x2019;操作数具有不可能的约束_C_Gcc_Assembly - Fatal编程技术网

gcc中的扩展asm:‘;asm&x2019;操作数具有不可能的约束

gcc中的扩展asm:‘;asm&x2019;操作数具有不可能的约束,c,gcc,assembly,C,Gcc,Assembly,这个函数“strcpy”的目的是将src的内容复制到dest,结果很好:显示两行“Hello\u src” #包括 静态内联字符*strcpy(字符*dest,常量字符*src) { int d0、d1、d2; __asm\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu “stosb\n\t” testb%%al,%%al\n\t “jne 1b” :“=&S”(d0)、“=&D”(d1)、“

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

#包括
静态内联字符*strcpy(字符*dest,常量字符*src)
{
int d0、d1、d2;
__asm\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
“stosb\n\t”
testb%%al,%%al\n\t
“jne 1b”
:“=&S”(d0)、“=&D”(d1)、“=&a”(d2)
:“0”(src),“1”(目的地)
:“记忆”);
返回目的地;
}
内部主(空){
char src_main[]=“Hello_src”;
char dest_main[]=“你好”;
strcpy(目的地总管、src总管);
puts(src_干管);
put(dest_main);
返回0;
}
  • 我试图将行
    :“0”(src)、“1”(dest)
    更改为
    :“S”(src)、“D”(dest)
    ,出现错误:
    “asm”操作数具有不可能的约束。我就是不明白。我认为这里的“0”/“1”指定了与第0/1个输出变量相同的约束。第0次输出的约束是
    =&S
    ,第1次输出的约束是
    =&D
    。如果我更改0-->S,1-->D,则不会有任何错误。怎么了

  • “clobbered寄存器”或earlyclobber操作数(&)有什么用处吗?我尝试删除“&”或“memory”,这两种情况的结果都与原始情况相同:输出两行“Hello_src”字符串。那么,我为什么要使用“撞坏”的东西呢


  • earlyclobber
    &
    表示在使用输入之前写入特定输出。因此,编译器不能将任何输入分配到同一寄存器。显然,使用
    0
    /
    1
    样式会覆盖该行为

    当然,打击者列表也有重要用途。编译器不会解析您的汇编代码。它需要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
    会发生什么:返回值将被覆盖。

    :“=&S”(d0)、“=&D”(d1)、“=&a”(d2)
    行无效,删除它后,您可以更改“0”和“1”那么,这是否意味着编译器将尝试将每个被破坏的寄存器恢复到其原始值,从而确保内联汇编代码不会影响任何寄存器?如果是这样,我只是尝试了另一行:
    asm(“addl%%ebx,%%eax”:::%eax,%ebx”),但我发现编译器没有做任何事情来恢复“%eax”或“%ebx”的值。它只恢复它需要的值的寄存器。它可能只是改变代码生成,从而避免使用被破坏的寄存器。谢谢。我得到了它。但我还是有点困惑。对于
    &
    0/1
    操作数,我认为它们完全相互冲突
    &
    告诉输出变量不要使用与输入变量相同的寄存器,但是
    0/1
    告诉输入变量使用与输出变量相同的寄存器。怎么解释呢?
    call    foo
    movl    %eax, %edx
    nop
    movl    %edx, %eax