RDTSC 和系统调用,sys_read 和 sys_write
RDTSC and system calls, sys_read and sys_write
我正在尝试使用 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 [=12=]x80
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;
}
当我 运行 程序出现分段错误(核心转储)错误时。
您的问题与 RDTSC 无关,而与您的 print()
函数有关。将您的问题简化为 MCVE 会缩小范围。
movl $STDOUT, %ebx
您在 print
函数中破坏了 EBX。你 save/restore 它在你的 rdtsc 函数中是正确的,但不是 print
。 EBX 是一个 call-preserved 寄存器,编译器将假设它在函数调用中保持其值。
如果您编译了一个 32 位 PIE 可执行文件,它可能使用 EBX 作为 GOT 指针,因此在尝试获取 printf
或更早的某个时间点的字符串文字地址时会出错。
具有讽刺意味的是,如果您使用 lfence
而不是 cpuid
来序列化它,则不需要在 rdtsc
函数中使用 save/restore EBX。
或者更好,使用 _mm_lfence()
+ __rdtsc()
内在函数而不是 asm。参见 Get CPU cycle count?
我正在尝试使用 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 [=12=]x80
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;
}
当我 运行 程序出现分段错误(核心转储)错误时。
您的问题与 RDTSC 无关,而与您的 print()
函数有关。将您的问题简化为 MCVE 会缩小范围。
movl $STDOUT, %ebx
您在 print
函数中破坏了 EBX。你 save/restore 它在你的 rdtsc 函数中是正确的,但不是 print
。 EBX 是一个 call-preserved 寄存器,编译器将假设它在函数调用中保持其值。
如果您编译了一个 32 位 PIE 可执行文件,它可能使用 EBX 作为 GOT 指针,因此在尝试获取 printf
或更早的某个时间点的字符串文字地址时会出错。
具有讽刺意味的是,如果您使用 lfence
而不是 cpuid
来序列化它,则不需要在 rdtsc
函数中使用 save/restore EBX。
或者更好,使用 _mm_lfence()
+ __rdtsc()
内在函数而不是 asm。参见 Get CPU cycle count?