我正在尝试使用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/