在gcc中扩展了asm:"asm"操作数具有不可能的约束 [英] extended asm in gcc: ‘asm’ operand has impossible constraints

查看:235
本文介绍了在gcc中扩展了asm:"asm"操作数具有不可能的约束的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此函数"strcpy"旨在将 src 的内容复制到 dest ,并且效果很好:显示两行"Hello_src".

This function "strcpy" aims to copy the content of src to dest, and it works out just fine: display two lines of "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个输出的约束为=&S,第1个输出的约束为=&D.如果我将0-> S,1-> D更改为正确,则应该没有任何错误.怎么了?

  1. I tried to change the line : "0"(src),"1"(dest) to : "S"(src),"D"(dest), the error occurred: ‘asm’ operand has impossible constraints. I just cannot understand. I thought that "0"/"1" here specified the same constraint as the 0th/1th output variable. the constraint of 0th output is =&S, te constraint of 1th output is =&D. If I change 0-->S, 1-->D, there shouldn't be any wrong. What's the matter with it?

集群寄存器"或EarlyClobber操作数(&)有什么用吗?我尝试删除&"或内存",两种情况下的结果都与原始情况相同:输出两行"Hello_src"字符串.那么,为什么我要使用笨拙的"东西呢?

Does "clobbered registers" or the earlyclobber operand(&) have any use? I try to remove "&" or "memory", the result of either circumstance is the same as the original one: output two lines of "Hello_src" strings. So why should I use the "clobbered" things?

推荐答案

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

The earlyclobber & means that the particular output is written before the inputs are consumed. As such, the compiler may not allocate any input to the same register. Apparently using the 0/1 style overrides that behavior.

当然,清单清单也具有重要的用途.编译器不会解析您的汇编代码.它需要清单列表来确定您的代码将修改哪些寄存器.您最好不要撒谎,否则可能会潜入一些小错误.如果要查看其效果,请尝试诱使编译器在asm块周围使用寄存器:

Of course the clobber list also has important use. The compiler does not parse your assembly code. It needs the clobber list to figure out which registers your code will modify. You'd better not lie, or subtle bugs may creep in. If you want to see its effect, try to trick the compiler into using a register around your asm block:

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

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

Relevant part of the generated assembly code:

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

请注意,编译器必须将eax的返回值保存到edx中,因为它认为将修改eax.通常,它只会将其保留在eax中,因为稍后将需要使用它.在这里,您可以想象如果您的asm代码在不通知编译器的情况下修改了eax会发生什么:返回值将被覆盖.

Notice how the compiler had to save the return value from foo into edx because it believed that eax will be modified. Normally it would just leave it in eax, since that's where it will be needed later. Here you can imagine what would happen if your asm code did modify eax without telling the compiler: the return value would be overwritten.

这篇关于在gcc中扩展了asm:"asm"操作数具有不可能的约束的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆