【发布时间】:2016-02-05 15:21:25
【问题描述】:
我正在做一个程序,此时我需要让它高效。
我正在使用 Haswell 微架构(64 位)和“g++”。
目标是使用ADC 指令,直到循环结束。
//I removed every carry handlers from this preview, yo be more simple
size_t anum = ap[i], bnum = bp[i];
unsigned carry;
// The Carry flag is set here with an common addtion
anum += bnum;
cnum[0]= anum;
carry = check_Carry(anum, bnum);
for (int i=1; i<n; i++){
anum = ap[i];
bnum = bp[i];
//I want to remove this line and insert the __asm__ block
anum += (bnum + carry);
carry = check_Carry(anum, bnum);
//This block is not working
__asm__(
"movq -64(%rbp), %rcx;"
"adcq %rdx, %rcx;"
"movq %rsi, -88(%rbp);"
);
cnum[i] = anum;
}
CF 是否在第一次添加中设置only?还是每次我执行ADC 指令时都会这样?
我认为问题出在CF 的loss 上,每次循环 完成。如果是这个问题,我该如何解决?
【问题讨论】:
-
那永远不会那样工作,进位标志可以在您到达那里时更改。如果你坚持要优化这个,你应该用纯 asm 编写整个循环,这样你就不必为 gcc 内联 asm 而烦恼,这是一个复杂的野兽。
-
我所有的代码都不在这里。这只是主要的谷物。在我的代码中,我确实使用另一个局部变量进行控制,但我想删除它。
-
代码到底应该做什么?对于循环的每次迭代,是否要使用第 2 行设置的相同 CF 值?如果是这样,您需要使用
setc指令或其他东西来保留标志的状态。请记住,大多数 x86 指令设置了标志,这会破坏标志的旧状态。 -
如果您不想自己保存标志,唯一的方法是将整个东西放入 asm 中,这样您就可以确保 CF 没有被破坏。最好的办法就是把它放到一个单独的 asm 模块中。
-
这段代码是做一个非常大的数字的加法。我想在每次迭代中使用最后一次加法的结果,以了解最后一次是否发生溢出。如果有指令可以破坏标志的旧状态,我如何确保不会发生这种情况?
CF不是在我每次执行“ADC”指令时设置的吗?如果是这样,我明白出了什么问题。
标签: c++ assembly cpu-registers bignum multiprecision