gpt4 book ai didi

gcc - 将 Pentium II 时序代码转换为内联汇编?

转载 作者:行者123 更新时间:2023-12-02 08:21:01 25 4
gpt4 key购买 nike

我正在尝试在 GCC 中使用以下代码。它正在抛出错误(我猜是因为 __asm)。为什么这种简单易用的格式在 GCC 中不起作用? Syntax of extended assembly在这里提供。在内联汇编中使用更多变量时,我感到很困惑。有人可以将以下程序转换为适当的形式,并在使用变量的地方给出必要的解释。

    int time, subtime;
float x = 5.0f;
__asm {
cpuid
rdtsc
mov subtime, eax
cpuid
rdtsc
sub eax, subtime
mov subtime, eax // Only the last value of subtime is kept
// subtime should now represent the overhead cost of the
// MOV and CPUID instructions
fld x
fld x
cpuid // Serialize execution
rdtsc // Read time stamp to EAX
mov time, eax
fdiv // Perform division
cpuid // Serialize again for time-stamp read
rdtsc
sub eax, time // Find the difference
mov time, eax
}

.

最佳答案

您的问题实际上是一个代码转换问题,对于 Stackoverflow 通常是题外话。然而,答案可能对其他读者有益。

此代码是原始源 Material 的转换,并不意味着增强。实际的 FDIV/FDIVPFLD 可以减少为单个 FLDFDIV/FDIVP 因为您将浮点值除以自身。正如 Peter Cordes 指出的那样,您可以使用 FLD1 将值 1.0 加载到堆栈顶部。 .这是可行的,因为将 任何 数除以自身(除了 0.0)将花费与将 5.0 除以自身相同的时间。这将消除将变量 x 传递到汇编程序模板的需要。

您使用的代码是 documented by Intel 的变体20 年前的 Pentium II。描述了对该处理器正在发生的事情的讨论。不同之处在于您使用的代码不会执行该文档中描述的热身。我认为这种机制不会在现代处理器和操作系统上运行得过于出色(警告)。

有问题的代码旨在测量单个 FDIV 所需的时间。指令来完成。假设你真的想转换这个特定的代码,你将不得不使用 GCC extended assembler templates .扩展汇编程序模板对于初次使用 GCC 的开发人员来说并不容易使用。对于汇编代码,您甚至可以考虑将代码放入单独的汇编文件中,单独进行汇编,然后从 C 中调用它。

汇编程序模板使用 input constraintsoutput constraints将数据传入和传出模板(与 MSVC 不同)。它还使用 clobber list指定可能已更改但未显示为输入或输出的寄存器。默认情况下,GCC 内联汇编使用 ATT syntax而不是 INTEL

使用带有 ATT 语法的扩展汇编程序的等效代码如下所示:

#include <stdio.h>
int main()
{
int time, subtime;
float x = 5.0f;
int temptime;
__asm__ (
"rdtsc\n\t"
"mov %%eax, %[subtime]\n\t"
"cpuid\n\t"
"rdtsc\n\t"
"sub %[subtime], %%eax\n\t"
"mov %%eax, %[subtime]\n\t"
/* Only the last value of subtime is kept
* subtime should now represent the overhead cost of the
* MOV and CPUID instructions */
"flds %[x]\n\t"
"flds %[x]\n\t" /* Alternatively use fst to make copy */
"cpuid\n\t" /* Serialize execution */
"rdtsc\n\t" /* Read time stamp to EAX */
"mov %%eax, %[temptime]\n\t"
"fdivp\n\t" /* Perform division */
"cpuid\n\t" /* Serialize again for time-stamp read */
"rdtsc\n\t"
"sub %[temptime], %%eax\n\t"
"fstp %%st(0)\n\t" /* Need to clear FPU stack before returning */
: [time]"=a"(time), /* 'time' is returned via the EAX register */
[subtime]"=r"(subtime), /* return reg for subtime */
[temptime]"=r"(temptime) /* Temporary reg for computation
This allows compiler to choose
a register for temporary use. Register
only for BOTH so subtime and temptime
calc are based on a mov reg, reg */

: [x]"m"(x) /* X is a MEMORY reference (required by FLD) */
: "ebx", "ecx", "edx"); /* Registers clobbered by CPUID
but not listed as input/output
operands */

time = time - subtime; /* Subtract the overhead */
printf ("%d\n", time); /* Print total time of divide to screen */
return 0;
}

关于gcc - 将 Pentium II 时序代码转换为内联汇编?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37315650/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com