RDTSC и системные вызовы, sys_read и sys_write - PullRequest
1 голос
/ 12 июня 2019

Я пытаюсь подсчитать, используя rdtsc, сколько циклов требуется, чтобы написать что-то, используя sys_write. Я смог протестировать функции printf и scanf. Они работали правильно, и теперь у меня проблема с системными вызовами.

На мой взгляд, проблема в регистрах% eax и% edx, потому что rdtsc сохраняет результат в этих регистрах.

write.s

.data
SYS_EXIT = 1
SYS_WRITE = 4
STDOUT = 1
EXIT_SUCCES = 0
text: .ascii  "Hello from assembler\n"
textLength: .long   . - text

.section .text
.globl print
.type print, @function             
print:


  movl $SYS_WRITE, %eax
  movl $STDOUT, %ebx
  movl $text, %ecx
  movl textLength, %edx
  int $0x80

  ret

rdtsc.s

.data
.text

.globl rdtsc

rdtsc:
   push %ebx
   xor %eax, %eax
   cpuid
   rdtsc
   pop %ebx
ret

main.c


#include <stdio.h>

unsigned long long rdtsc();
extern void print();
unsigned long long startTime, stopTime, workingTime;

int main (void)
{
            startTime = rdtsc();
        print();
        stopTime = rdtsc();
        workingTime = stopTime - startTime;
        printf("Cycles %llu\n", workingTime);
return 0;
}

Когда я запускаю программу, я получаю ошибку Сегментация (ядро сброшено).

1 Ответ

3 голосов
/ 12 июня 2019

Ваша проблема не имеет ничего общего с RDTSC, и все, что связано с вашей print() функцией.Сокращение вашей проблемы до MCVE сузило бы это.

movl $STDOUT, %ebx

Вы забили EBX в своей функции print .Вы сохраняете / восстанавливаете его правильно в вашей функции rdtsc, но не print.EBX - это регистр, сохраняющий вызовы, который, как предполагает компилятор, сохраняет свое значение при вызовах функций.

Если вы скомпилировали 32-битный исполняемый файл PIE, он, вероятно, использовал EBX для указателя GOT и, таким образом, выдает ошибки при попыткеполучить адрес строкового литерала для printf или в какой-то момент раньше.


Как ни странно, вам не нужно сохранять / восстанавливать EBX в вашей функции rdtsc, если вы используете lfenceчтобы сериализовать его вместо cpuid.

или, что еще лучше, использовать _mm_lfence() + __rdtsc() intrinsics вместо asm.См. Получить количество циклов ЦП?

...