将GCC内联程序集CMOV转换为Visual Studio汇编器 [英] Convert GCC Inline Assembly CMOV to Visual Studio Assembler
问题描述
在文章线性与二进制搜索,它是使用CMOV指令的二进制搜索的快速实现.我想在VC ++中实现此功能,因为我正在处理的应用程序依赖于Binary Search的性能.
In the article Linear vs. Binary Search, there is a fast implementation of binary search which uses the CMOV instruction. I would like to implement this in VC++ as the application I'm working on relies on the performance of Binary Search.
该实现具有一些GCC内联汇编器,其声明如下:
The implementation has some GCC inline assembler which is declared as follows:
static int binary_cmov (const int *arr, int n, int key) {
int min = 0, max = n;
while (min < max) {
int middle = (min + max) >> 1;
asm ("cmpl %3, %2\n\tcmovg %4, %0\n\tcmovle %5, %1"
: "+r" (min),
"+r" (max)
: "r" (key), "g" (arr [middle]),
"g" (middle + 1), "g" (middle));
// Equivalent to
// if (key > arr [middle])
// min = middle + 1;
// else
// max = middle;
}
return min;
}
我想将此GCC汇编程序转换为与Microsoft Visual Studio兼容的汇编程序,但作为GCC菜鸟不知道从哪里开始.
I'd like to convert this GCC Assembler to Microsoft Visual Studio compatible assembler, but as a GCC noob wouldn't know where to start.
任何人都可以帮忙,或者至少解释一下GCC内联汇编程序吗? TIA!
Can anyone help, or at least explain the GCC Inline Assembler? TIA!
推荐答案
重构代码以更好地向编译器表达意图:
refactoring the code in order to better express intent to the compiler:
int binary_cmov (const int *arr, int n, int key)
{
int min = 0, max = n;
while (min < max)
{
int middle = (min + max) >> 1;
min = key > arr[middle] ? middle + 1 : min;
max = key > arr[middle] ? max : middle;
}
return min;
}
使用gcc5.3 -O3,产量:
With gcc5.3 -O3, yields:
binary_cmov(int const*, int, int):
xorl %eax, %eax
testl %esi, %esi
jle .L4
.L3:
leal (%rax,%rsi), %ecx
sarl %ecx
movslq %ecx, %r8
leal 1(%rcx), %r9d
movl (%rdi,%r8,4), %r8d
cmpl %edx, %r8d
cmovl %r9d, %eax
cmovge %ecx, %esi
cmpl %eax, %esi
jg .L3
rep ret
.L4:
rep ret
故事的寓意-不要嵌入汇编器.您要做的就是使代码不可移植.
moral of the story - don't embed assembler. All you do is make the code non-portable.
走得更远...
为什么不更明确地表达意图?
why not express intent even more explicitly?
#include <utility>
template<class...Ts>
auto sum(Ts...ts)
{
std::common_type_t<Ts...> result = 0;
using expand = int[];
void(expand{ 0, ((result += ts), 0)... });
return result;
}
template<class...Ts>
auto average(Ts...ts)
{
return sum(ts...) / sizeof...(Ts);
}
int binary_cmov (const int *arr, int n, int key)
{
int min = 0, max = n;
while (min < max)
{
int middle = average(min, max);
auto greater = key > arr[middle];
min = greater ? middle + 1 : min;
max = greater ? max : middle;
}
return min;
}
编译器输出:
binary_cmov(int const*, int, int):
xorl %eax, %eax
testl %esi, %esi
jle .L4
.L3:
leal (%rax,%rsi), %ecx
movslq %ecx, %rcx
shrq %rcx
movslq %ecx, %r8
leal 1(%rcx), %r9d
movl (%rdi,%r8,4), %r8d
cmpl %edx, %r8d
cmovl %r9d, %eax
cmovge %ecx, %esi
cmpl %eax, %esi
jg .L3
rep ret
.L4:
rep ret
这篇关于将GCC内联程序集CMOV转换为Visual Studio汇编器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!