cassemblyx86attrdtsc

RDTSC and system calls, sys_read and sys_write


I'm trying to count, using rdtsc, how many cycles it takes write something using sys_write. I was able to test the printf and scanf functions. They worked correctly, and now I have a problem with system calls.

In my opinion, the problem is with %eax and %edx registers, because rdtsc saves the result in these registers.

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

When I run the program I get a Segmentation fault (core dumped) error.


Solution

  • Your problem has nothing to do with RDTSC, and everything to do with your print() function. Reducing your problem to a MCVE would have narrowed that down.

    movl $STDOUT, %ebx

    You clobber EBX in your print function. You save/restore it correctly in your rdtsc function, but not print. EBX is a call-preserved register that the compiler will assume keeps its value across function calls.

    If you compiled a 32-bit PIE executable, it probably used EBX for a GOT pointer, and thus faults when trying to get the address of the string literal for printf or at some point earlier.


    Ironically, you don't need to save/restore EBX in your rdtsc function if you use lfence to serialize it instead of cpuid.

    Or better, use _mm_lfence() + __rdtsc() intrinsics instead of asm. See Get CPU cycle count?