2013-02-09 4 views
10

Отказ от ответственности: Слова не могут описать, как я ненавижу AT & T синтаксисаКакой код встроенной сборки подходит для rdtscp?

стиля У меня есть проблема, которую я надеюсь, что вызывается регистр затирание. Если нет, у меня гораздо большая проблема.

Первый вариант я использовал

static unsigned long long rdtscp(void) 
{ 
    unsigned int hi, lo; 
    __asm__ __volatile__("rdtscp" : "=a"(lo), "=d"(hi)); 
    return (unsigned long long)lo | ((unsigned long long)hi << 32); 
} 

Я заметил, что нет «затирания» вещи в этой версии. Является ли это проблемой, я не знаю ... Я полагаю, это зависит от того, компилятор строит функцию или нет. Использование этой версии вызывает у меня проблемы , которые не всегда воспроизводятся.

Следующая версия я нашел

static unsigned long long rdtscp(void) 
{ 
    unsigned long long tsc; 
    __asm__ __volatile__(
     "rdtscp;" 
     "shl $32, %%rdx;" 
     "or %%rdx, %%rax" 
     : "=a"(tsc) 
     : 
     : "%rcx", "%rdx"); 

    return tsc; 
} 

Это успокоительно нечитаемое и официальный вид, но, как я сказал, что мой вопрос не всегда воспроизводим, так что я просто пытаюсь исключить одну возможную причину моего проблема.

Причина, по которой I считает первой проблемой, является то, что она перезаписывает регистр, который ранее содержал параметр функции.

Что такое ... версия 1 или версия 2 или оба?

+7

Поделитесь своей ненавистью к синтаксису. Когда я дойду до этого момента, я ищу встроенные функции компилятора или просто поместите функции в файл .s и соберу их самостоятельно ... –

+0

@MichaelDorgan VC++ предлагает прекрасный внутренний, gcc, к сожалению, нет. – James

+8

+1 только для 'detest AT & T style syntax' –

ответ

18

Вот C++ кода, который будет возвращать TSC и хранить вспомогательный 32 бит в ссылочном параметр

static inline uint64_t rdtscp(uint32_t & aux) 
{ 
    uint64_t rax,rdx; 
    asm volatile ("rdtscp\n" : "=a" (rax), "=d" (rdx), "=c" (aux) : :); 
    return (rdx << 32) + rax; 
} 

Лучше сделать shift и add объединить оба 32-битные половина в заявлении C++, а чем inline, это позволяет компилятору планировать эти инструкции по своему усмотрению.

+0

Это тоже не clobber ECX? Если нет, я просто удалю свой ответ и позвоню тебе. –

+2

Да, спецификация «= c» сообщает компилятору, что ECX будет удерживать вывод, что означает, что он сбитый – amdn

+0

Спасибо.Первая версия не маркировала 'ecx' как сбитую. Этот регистр сначала содержал значение параметра, которое использовалось в условном выражении, которое в случае неудачи называлось 'std :: terminate()'. Когда это было сбито, состояние, очевидно, проверяло неправильную вещь! – James

1

В соответствии с this, эта операция clobbers EDX и ECX. Вам нужно отметить те регистры, которые были сбиты, что и делает второй. Кстати, это ссылка, в которой вы получили вышеуказанный код, или вы нашли его в другом месте? Он также показывает несколько других вариантов для таймингов, а это довольно аккуратно.

+0

Неверная инструкция. Это 'rdtscp', а не' rdtsc', и любой вывод, как известно, сбивается, поэтому его не нужно указывать. Проблема в том, что 'rdtscp' * также * уничтожает ecx, какая версия 2 помечается как clobbered, но версия 1 не работает. – ughoavgfhw

+0

Так получилось, и у нас есть ответ для него. Я очищу его ... –

+0

Оставив это здесь для другой ссылки SO, которая может быть полезна, хотя выше ответ лучше. –

2

Я думаю, что вы можете очень спокойно относятся к this document, не только для проверки, но и узнавая немного более глубокий анализ о точности RDTSC и RDTSCP.

Надеюсь, это поможет.

Смежные вопросы