Как мне написать ассемблер в C ++ для добавления (время теста) - PullRequest
0 голосов
/ 09 ноября 2010

Я хочу узнать, сколько времени будет медленнее, если я буду выполнять простую операцию, такую ​​как 1 + 1 и плюс (int l, int r), которая выполняет l + r и вызывает исключение при переполнении, вот пример кода с _C и _V - перенос и переполнение. Код исключения может быть написан по-другому, если хотите.

Как мне написать это, чтобы я мог быстро проверить перенос / переполнение и выдать исключение, если это правда? Я никогда не делал прыжки (или даже некоторые основы) в сборке, поэтому я немного невежествен даже после поиска в Google.

Это должно работать в x32 comps. В настоящее время я использую Intel Core Duo с установленным 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 ]

2 голосов
/ 09 ноября 2010

Вы хотите, чтобы код C / C ++ выполнял эти операции, или вы хотите знать, как это сделать на языке ассемблера x86?

В C / C ++ определить перенос легко:

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

Переполнение немного сложнее. Обычно переполнение помечается, когда два операнда имеют один и тот же знак, но результат имеет другой знак. На двух дополнительных архитектурах, таких как x86, это можно записать так:

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

MSB (бит знака) l ^ r будет равен 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) - это зависит от используемого компилятора и архитектуры.

0 голосов
/ 09 ноября 2010

Вот тестовый код, который я использую

-edit- Я тестировал на VS 2010 за пределами IDE и в GCC. GCC намного быстрее, так как VC плохо оптимизирует переменные. (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;
}
0 голосов
/ 09 ноября 2010

Сдвиньте бит обоих входов вправо по одному. Добавьте их обоих, затем проверьте крайний левый бит.

l>>1;
r>>1;
int result = l+r;
if (result>>((sizeof(int)*8)-1)) { /* handle overflow */ }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...