Assembly 确定X86程序集中的内存访问时间
我试图确定访问两个内存地址的时间,这两个地址之间有一个特定的增量。我的代码必须混合使用x86和C,并将“裸机”运行(没有任何操作系统;编辑:我实际上是在修改memtest),以获得最精确的结果 我比x86更习惯于ARM组装,因此我可能犯了一些错误(我想知道,为什么mov在x86中做了这么多不同的事情)。我的代码如下Assembly 确定X86程序集中的内存访问时间,assembly,x86,Assembly,X86,我试图确定访问两个内存地址的时间,这两个地址之间有一个特定的增量。我的代码必须混合使用x86和C,并将“裸机”运行(没有任何操作系统;编辑:我实际上是在修改memtest),以获得最精确的结果 我比x86更习惯于ARM组装,因此我可能犯了一些错误(我想知道,为什么mov在x86中做了这么多不同的事情)。我的代码如下 inline unsigned timeread (ulong addr, ulong delta, int iter) { ulong daddr; int i;
inline unsigned timeread (ulong addr, ulong delta, int iter)
{
ulong daddr;
int i;
ulong st_low, st_high;
ulong end_low, end_high;
daddr = addr + delta;
asm __volatile__ ("rdtsc":"=a" (st_low),"=d" (st_high));
for (i = 0; i < iter; ++i)
{
asm __volatile__ (
"movl (%0), %%eax\n\t"
:
: "D" (addr)
: "eax"
);
asm __volatile__ (
"movl (%0), %%eax\n\t"
:
: "D" (daddr)
: "eax"
);
}
asm __volatile__ ("rdtsc":"=a" (end_low),"=d" (end_high));
asm __volatile__ (
"subl %2,%0\n\t"
"sbbl %3,%1"
: "=a" (end_low), "=d" (end_high)
: "g" (st_low), "g" (st_high),
"0" (end_low), "1" (end_high)
);
return end_low;
}
inline unsigned timeread(ulong addr、ulong delta、int iter)
{
乌隆达德;
int i;
乌龙街低,街高;
ulong端低,端高;
daddr=addr+delta;
asm挥发性(“rdtsc”):“=a”(st_低)、“=d”(st_高));
对于(i=0;i
我正在使用gcc并使用标志-march=i486-m32进行编译
编辑:在调用该函数之前,我调用memtest提供的一个函数,set_cache(0),以便停用缓存(至少它是这么说的)。相反,调用set_cache(1)可以极大地减少执行时间(我从~2000个周期下降到抛开代码是否实际测量了您想要的值的问题不谈,您的代码是正确的。英特尔x86指令集不遵循ARM指令集设计时使用的相同原则。RISC有专门用于加载和存储到内存的单独指令。这与早期的CPU设计风格(追溯命名)不同,大多数指令都可以直接访问内存。不仅仅是移动指令,还可以执行添加和跳转等操作。因此,是的,您的MOVL指令在内存中加载32位值的EAX 请注意,由于您对两条MOVL asm语句都使用了
“D”
约束,编译器必须在每条asm语句之前重新加载EDI。由于没有明显的理由将其约束到EDI,我建议使用“r”
约束,以便编译器可以选择两个不同的寄存器。启用优化后,编译器可以在循环外加载这两个寄存器一次,而不是在循环过程中每次加载一次。(如果不使用优化,则编译器将以任何一种方式加载寄存器,其中addr
和daddr
在每次循环迭代期间存储在堆栈上。)
例如:
asm volatile (
"movl (%0), %%eax\n\t"
:
: "r" (addr)
: "eax"
);
asm volatile (
"movl (%0), %%eax\n\t"
:
: "r" (daddr)
: "eax"
);
我不同意你的说法,这是C。在C中,整数和指针是不同的。这看起来不是很有用,实际上会发生的是两次内存访问,然后是大量缓存访问。你实际上没有问任何问题,但正如harold所说,这似乎没有衡量任何有用的东西。在上面执行这段代码也会很困难“裸机”作为GCC将生成32位代码。@EOF:代码基于memtest,我承认有些东西并不特别漂亮。@harold:在调用函数之前,缓存已被停用。