c - RDTSC 和系统调用,sys_read 和 sys_write
问题描述
我正在尝试使用 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;
}
当我运行程序时,我得到一个分段错误(核心转储)错误。
解决方案
您的问题与 RDTSC 无关,与您的print()
功能有关。将您的问题减少到 MCVE 会缩小范围。
movl $STDOUT, %ebx
你在你的print
函数中破坏了 EBX 。您在 rdtsc 函数中正确保存/恢复它,但不是print
. EBX 是一个调用保留寄存器,编译器将假定它在函数调用中保持其值。
如果您编译了一个 32 位 PIE 可执行文件,它可能使用 EBX 作为 GOT 指针,因此在尝试获取字符串文字的地址时printf
或在更早的某个时间点时出错。
具有讽刺意味的是,rdtsc
如果您使用lfence
序列化而不是cpuid
.
或者更好的是,使用_mm_lfence()
+__rdtsc()
内在函数而不是 asm。请参阅获取 CPU 周期计数?
推荐阅读
- java - 验证来自 Java 服务的 Hive 查询
- javascript - 如何等待http请求以角度8中的订阅方法返回响应?
- python - 表单类中的访问变量?
- gitlab - 哪个静态站点生成器具有最完整的 GitLab Flavored Markdown 支持?
- typescript - 函数参数的类型是否不应该支持 TypeScript 中的 `subtype`?
- java - 将布尔值传递给需要布尔值的方法
- vmware - 将 Vmware VMDK 转换为 Hyper-V
- ms-access - 如何在 ACCESS QUERY 中创建过去 7 天、30 天累积平均的滚动/移动平均线?
- gcc - 针对不同操作系统的交叉编译 GCC
- r - 如何在 R 中使用 tab_model 将 p.value 显着性符号 0.1 输出为“+”