1

我正在尝试使用 rdtsc 计算使用 sys_write 写入内容需要多少个周期。我能够测试 printf 和 scanf 函数。它们工作正常,现在我遇到了系统调用问题。

在我看来,问题出在 %eax 和 %edx 寄存器上,因为 rdtsc 将结果保存在这些寄存器中。

写.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

主程序


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

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

4

1 回答 1

3

您的问题与 RDTSC 无关,与您的print()功能有关。将您的问题减少到 MCVE 会缩小范围。

movl $STDOUT, %ebx

你在你的print函数中破坏了 EBX 。您在 rdtsc 函数中正确保存/恢复它,但不是print. EBX 是一个调用保留寄存器,编译器将假定它在函数调用中保持其值。

如果您编译了一个 32 位 PIE 可执行文件,它可能使用 EBX 作为 GOT 指针,因此在尝试获取字符串文字的地址时printf或在更早的某个时间点时出错。


具有讽刺意味的是,rdtsc如果您使用lfence序列化而不是cpuid.

或者更好的是,使用_mm_lfence()+__rdtsc()内在函数而不是 asm。请参阅获取 CPU 周期计数?

于 2019-06-12T13:09:20.167 回答