在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; }
如果我使用带有“int”返回值的“sbb%0,%0”而不是带有“bool”返回值的“setc%0”,那么还有两条额外的指令:在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]
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;