开发者

how do i write assembly in C++ for adding (time test)

I want to time how much slower it is if i were开发者_如何学编程 to do a simple operation like 1+1 and plus(int l,int r) which does l+r and throws an exception on overflow heres some example code with _C and _V being carry and overflow. The exception code can be written differently if you like.

How do i write it so i can quickly test for carry/overflow and throw an exception if it is true? I never did jumps (or even some of the basics) in assembly so i a bit clueless even after googling.

This should work in x32 comps. Currently i am running on a Intel Core Duo which has the x86, x86-64 set

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;
}


Do you want C/C++ code to perform these operations, or do you want to know how to do it in x86 assembly language?

In C/C++, determining the carry is easy:

int _C = (v < l); // "v < r" works too

The overflow is a bit more complicated. Normally overflow is flagged when the two operands have the same sign yet the result has a different sign. On two's complement architectures such as x86, this can be written as:

int _V = ((l ^ r) >= 0) && ((l ^ v) < 0);

The MSB (sign bit) of l ^ r will be 0 if and only if the signs agree, and similarly l ^ v will have a nonzero sign bit (=value less than zero) if and only if l and v have opposite signs.

If you want to write it in assembly, you just do the add and use a jc or jo respectively to jump to the carry/overflow handler. However, you can't easily throw C++ exceptions from assembly code. The easiest way to do this is probably to write a simple one-line function in C++ that throws the exception and call that from your assembly code. The final asm code will look something like this:

    ; Assuming eax=l, ebx=r
    add eax, ebx
    jc .have_carry
    ; Continue computation here...
.have_carry:
    call throw_overflow_exception

with the following C++ helper function defined somewhere:

extern "C" void throw_overflow_exception()
{
  throw 1; // or some other exception
}

You need the extern C to disable C++ name mangling for this function. There are other conventions to (e.g. some compilers add an underscore before or after C function names) - this depends on the compiler used and the architecture though.


Shift bit both inputs right by one. Add them both then test the left-most bit.

l>>1;
r>>1;
int result = l+r;
if (result>>((sizeof(int)*8)-1)) { /* handle overflow */ }


Here is the test code i end up using

-edit- I tested on VS 2010 outside of the IDE and in GCC. gcc is a lot faster as VC optimizes the variables poorly. (VS c++ moves the register back into V when assembly is used. It doesnt need to do that.) gcc shows little between the 3 test. The results varied from each run so often that they all looked like it was the same test. I couldnt tell. VS showed checking C flag without asm about 3x slower while with asm 6x slower.

#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;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜