我正在尝试使用rdtsc计算使用sys-write写东西需要多少周期。我能够测试printf和scanf函数。它们工作正常,现在系统调用有问题。
在我看来,问题在于%eax和%edx寄存器,因为rdtsc将结果保存在这些寄存器中。
写作

.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公司
.data
.text

.globl rdtsc

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


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

当我运行程序时,我得到一个分段错误(核心转储)错误。

最佳答案

您的问题与RDTSC无关,与print()函数有关。把你的问题简化为一个MCVE可以缩小范围。
movl $STDOUT, %ebx
你在你的print功能中破坏了EBX。您可以在rdtsc函数中正确保存/恢复它,但不能print。EBX是一个保留调用的寄存器,编译器将假定它在函数调用中保持其值。
如果您编译了一个32位PIE可执行文件,它可能使用EBX作为GOT指针,因此在尝试获取printf或之前某个点的字符串文本地址时出错。
具有讽刺意味的是,如果使用rdtsc来序列化EBX而不是lfence,则不需要在cpuid函数中保存/还原EBX。
或者更好的方法是使用_mm_lfence()+__rdtsc()内部函数而不是asm。见Get CPU cycle count?

关于c - RDTSC和系统调用sys_read和sys_write,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56562569/

10-11 18:50