在GCC风格的扩展内联asm中,是否可以输出一个;“虚拟化”;布尔值,例如进位标志? 如果我有下面的C++代码比较两个128位无符号整数,内联AMD-64 ASM:< /P> struct uint128_t { uint64_t lo, hi; }; inline bool operator< (const uint128_t &a, const uint128_t &b) { uint64_t temp; bool result; __asm__( "cmpq %3, %2;" "sbbq %4, %1;" "setc %0;" : // outputs: /*0*/"=r,1,2"(result), /*1*/"=r,r,r"(temp) : // inputs: /*2*/"r,r,r"(a.lo), /*3*/"emr,emr,emr"(b.lo), /*4*/"emr,emr,emr"(b.hi), "1"(a.hi)); return result; }

在GCC风格的扩展内联asm中,是否可以输出一个;“虚拟化”;布尔值,例如进位标志? 如果我有下面的C++代码比较两个128位无符号整数,内联AMD-64 ASM:< /P> struct uint128_t { uint64_t lo, hi; }; inline bool operator< (const uint128_t &a, const uint128_t &b) { uint64_t temp; bool result; __asm__( "cmpq %3, %2;" "sbbq %4, %1;" "setc %0;" : // outputs: /*0*/"=r,1,2"(result), /*1*/"=r,r,r"(temp) : // inputs: /*2*/"r,r,r"(a.lo), /*3*/"emr,emr,emr"(b.lo), /*4*/"emr,emr,emr"(b.hi), "1"(a.hi)); return result; },gcc,assembly,boolean,flags,inline-assembly,Gcc,Assembly,Boolean,Flags,Inline Assembly,如果我使用带有“int”返回值的“sbb%0,%0”而不是带有“bool”返回值的“setc%0”,那么还有两条额外的指令: mov r10, [r14] mov r11, [r14+8] cmp r10, [r15] sbb r11, [r15+8] sbb eax, eax test eax, eax jnz is_lessthan 我想要的是: mov r10, [r14]

如果我使用带有“int”返回值的“sbb%0,%0”而不是带有“bool”返回值的“setc%0”,那么还有两条额外的指令:

    mov    r10, [r14]
    mov    r11, [r14+8]
    cmp    r10, [r15]
    sbb    r11, [r15+8]
    sbb    eax, eax
    test   eax, eax
    jnz    is_lessthan
我想要的是:

    mov    r10, [r14]
    mov    r11, [r14+8]
    cmp    r10, [r15]
    sbb    r11, [r15+8]
    jc     is_lessthan
GCC扩展内联asm非常好,否则。但我希望它在各个方面都和内在函数一样好。我希望能够以CPU标志状态的形式直接返回布尔值,而无需将其“呈现”到通用寄存器中

这是可能的,或者GCC(和英特尔C++编译器,也允许使用这种形式的内联ASM)必须修改或重构,以使其成为可能?


另外,当我在做比较时,有没有其他方法可以改进我的比较运算符公式?

我不知道如何做到这一点。你可以考虑或者不认为这是一个改进:

inline bool operator< (const uint128_t &a, const uint128_t &b)
{
    register uint64_t temp = a.hi;
    __asm__(
        "cmpq %2, %1;"
        "sbbq $0, %0;"
        : // outputs:
        /*0*/"=r"(temp)
        : // inputs:
        /*1*/"r"(a.lo),
        /*2*/"mr"(b.lo),
        "0"(temp));

    return temp < b.hi;
}

现在我们已经过去了近7年,是的,gcc最终添加了对“输出旗帜”的支持(添加于6.1.0中,于2016年4月发布)。详细的文档是,但简而言之,它看起来是这样的:

    mov    r10, [r14]
    mov    r11, [r14+8]
    cmp    r10, [r15]
    sbb    r11, [r15+8]
    setc   al
    movzx  eax, al
    test   eax, eax
    jnz    is_lessthan
/* Test if bit 0 is set in 'value' */
char a;

asm("bt $0, %1"
    : "=@ccc" (a)
    : "r" (value) );

if (a)
   blah;
要理解
=@cc
:输出约束(需要
=
)的类型为
@cc
,后跟要使用的条件代码(在这种情况下,
c
,以参考进位标志)

好的,对于您的具体情况来说,这可能不再是一个问题(因为gcc现在支持直接比较128位数据类型),但是(目前)有1326人查看了这个问题。显然,人们对这一功能感兴趣

现在我个人倾向于这样的思想流派。但如果必须,可以(现在)使用“输出”标志


FWIW.

+1极好的改进。这比我在问题中发布的做得更好(用于进行数千字节的排序操作)。我仍然希望有一种直接返回携带标志的方法,所以我不会将其标记为“接受答案”,但是,做得很好。截至2013年,似乎仍然不可能直接返回携带标志。但这里有一份2011年的bug报告讨论了这样一个特性的可取性:。它链接到一个2001 Linux内核线程,也希望得到这样一个东西:。
/* Test if bit 0 is set in 'value' */
char a;

asm("bt $0, %1"
    : "=@ccc" (a)
    : "r" (value) );

if (a)
   blah;