如何在C ++中编写程序集进行添加(时间测试)

时间:2010-11-09 05:07:36

标签: c++ assembly

我想知道如果我做一个像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;
}

3 个答案:

答案 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将具有非零符号位(=值小于零)当且仅当lv的符号相反。

如果要在汇编中编写它,只需添加并分别使用jcjo跳转到进位/溢出处理程序。但是,您不能轻易地从汇编代码中抛出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;
}