我想知道如果我做一个像1 + 1和加号(int l,int r)这样的简单操作会慢一点,它会做l + r并在溢出时抛出异常继承一些带有_C的示例代码和_V正在进行和溢出。如果您愿意,可以使用不同的方式编写异常代码。
我如何编写它以便我可以快速测试进位/溢出并且如果它是真的则抛出异常? 我从来没有在汇编中跳过(甚至是一些基础知识)所以即使在谷歌搜索之后我也有点无能为力。
这应该适用于x32 comps。目前我正在使用具有x86,x86-64设置的英特尔酷睿双核处理器
unsigned int plus(unsigned int l, unsigned int r){
unsigned int v = l+r;
if (!_C) return v;
throw 1;
}
int plus(int l, int r){
int v = l+r;
if (!_V) return v;
throw 1;
}
答案 0 :(得分:2)
您是否希望C / C ++代码执行这些操作,或者您是否想知道如何使用x86汇编语言执行此操作?
在C / C ++中,确定进位很容易:
int _C = (v < l); // "v < r" works too
溢出有点复杂。当两个操作数具有相同的符号但结果具有不同的符号时,通常会标记溢出。在两个补码架构(如x86)上,可以写成:
int _V = ((l ^ r) >= 0) && ((l ^ v) < 0);
当且仅当符号一致时,l ^ r
的MSB(符号位)将为0,并且类似l ^ v
将具有非零符号位(=值小于零)当且仅当l
和v
的符号相反。
如果要在汇编中编写它,只需添加并分别使用jc
或jo
跳转到进位/溢出处理程序。但是,您不能轻易地从汇编代码中抛出C ++异常。最简单的方法是在C ++中编写一个简单的单行函数,抛出异常并从汇编代码中调用它。最终的asm代码看起来像这样:
; Assuming eax=l, ebx=r
add eax, ebx
jc .have_carry
; Continue computation here...
.have_carry:
call throw_overflow_exception
在某处定义了以下C ++帮助函数:
extern "C" void throw_overflow_exception()
{
throw 1; // or some other exception
}
您需要extern C
来禁用此函数的C ++名称修改。还有其他约定(例如,一些编译器在C函数名之前或之后添加下划线) - 这取决于所使用的编译器和架构。
答案 1 :(得分:0)
将两个输入右移一位。添加它们然后测试最左边的位。
l>>1;
r>>1;
int result = l+r;
if (result>>((sizeof(int)*8)-1)) { /* handle overflow */ }
答案 2 :(得分:0)
以下是我最终使用的测试代码
-edit-我在IDE之外和GCC中测试了VS 2010。由于VC很好地优化了变量,所以gcc要快得多。 (当使用汇编时,VS c ++将寄存器移回V.它不需要这样做。)gcc在3测试之间显示很少。每次运行的结果都不同,所以看起来它们都是相同的测试。我不知道。 VS显示检查C标志没有asm约3倍慢,而asm慢6倍。
#include <stdio.h>
#include <intrin.h>
int main(int argc, char*argv[])
{
try{
for(int n=0; n<10; n++){
volatile unsigned int v, r;
sscanf("0", "%d", &v);
sscanf("0", "%d", &r);
__int64 time = 0xFFFFFFFF;
__int64 start = __rdtsc();
for(int i=0; i<100000000; i++)
{
v=v+v;
#if 1
__asm jc e
continue;
e:
throw 1;
#endif
}
__int64 end = __rdtsc();
time = end - start;
printf("time: %I64d\n", time/10000000);
}
}
catch(int v)
{
printf("exception");
}
return 0;
}