获得更多 GPR 的 x86 汇编技巧
x86 assembly tricks to get more GPRs
我写了一个汇编程序,它在 x86-64 上需要 5 个 GPR,运行良好。但我正在尝试将其移植到 32 位 x86。编译器抱怨无法使用 5 个探地雷达。
x86-64 的代码如下:
__asm__("mov %0,%%r8\n\t"
"mov %1,%%r10\n\t"
"lfence\n\t"
"rdtsc\n\t"
"mov %%eax,%%edi\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"lfence\n\t"
"rdtsc\n\t"
"sub %%edi, %%eax\n\t"
"mov %%eax, (%%r10)\n\t"
:
:"r"(head),"r"(time_buf)
:"eax","edx","edi","r8","r10"
);
我该如何克服这个问题?
处理器:Intel® Core™2 双核处理器 T9400
你实际上不需要 5 个寄存器,你只需要 4 个。寄存器 EAX 和 EDX 被 RDTSC 指令破坏了,所以是两个。您需要另一个寄存器来保存第一条 RDTSC 指令的 EAX 值。那是三个。第四个寄存器是 head
指针。您正在使用的其他寄存器不需要,没有必要在 asm
语句中计算或存储经过的时间。你可以用普通的 C/C++ 代码做到这一点。
我会将您的 asm 语句重写为如下内容:
unsigned
foo(void *head) {
unsigned time_start, time_end;
__asm__("lfence\n\t"
"rdtsc\n\t"
"mov %%eax, %0\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"lfence\n\t"
"rdtsc"
: "=r" (time_start), "+r" (head), "=a" (time_end)
:
: "edx"
);
return time_end - time_start;
}
此 asm 语句让编译器尽可能选择寄存器。 EAX 和 EDX 的使用由 RDTSC 指令固定,但用于保存 time_start
时间戳和 head
指针的寄存器留给编译器选择。
除了少使用一个寄存器外,我的示例 asm 语句还具有无需修改即可在 32 位和 64 位中工作的优势。
我写了一个汇编程序,它在 x86-64 上需要 5 个 GPR,运行良好。但我正在尝试将其移植到 32 位 x86。编译器抱怨无法使用 5 个探地雷达。
x86-64 的代码如下:
__asm__("mov %0,%%r8\n\t"
"mov %1,%%r10\n\t"
"lfence\n\t"
"rdtsc\n\t"
"mov %%eax,%%edi\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"mov (%%r8), %%r8\n\t"
"lfence\n\t"
"rdtsc\n\t"
"sub %%edi, %%eax\n\t"
"mov %%eax, (%%r10)\n\t"
:
:"r"(head),"r"(time_buf)
:"eax","edx","edi","r8","r10"
);
我该如何克服这个问题?
处理器:Intel® Core™2 双核处理器 T9400
你实际上不需要 5 个寄存器,你只需要 4 个。寄存器 EAX 和 EDX 被 RDTSC 指令破坏了,所以是两个。您需要另一个寄存器来保存第一条 RDTSC 指令的 EAX 值。那是三个。第四个寄存器是 head
指针。您正在使用的其他寄存器不需要,没有必要在 asm
语句中计算或存储经过的时间。你可以用普通的 C/C++ 代码做到这一点。
我会将您的 asm 语句重写为如下内容:
unsigned
foo(void *head) {
unsigned time_start, time_end;
__asm__("lfence\n\t"
"rdtsc\n\t"
"mov %%eax, %0\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"mov (%1), %1\n\t"
"lfence\n\t"
"rdtsc"
: "=r" (time_start), "+r" (head), "=a" (time_end)
:
: "edx"
);
return time_end - time_start;
}
此 asm 语句让编译器尽可能选择寄存器。 EAX 和 EDX 的使用由 RDTSC 指令固定,但用于保存 time_start
时间戳和 head
指针的寄存器留给编译器选择。
除了少使用一个寄存器外,我的示例 asm 语句还具有无需修改即可在 32 位和 64 位中工作的优势。