C++ 在可移植C++;

C++ 在可移植C++;,c++,assembly,g++,x86-64,visual-c++-2010,C++,Assembly,G++,X86 64,Visual C++ 2010,我有一个简单的(但性能关键的)C算法(嵌入C++中)来操作数据缓冲区。。。该算法“自然”使用64位big-endian寄存器值,我希望使用汇编程序对此进行优化,以获得对进位标志和BSWAP的直接访问,从而避免一次操作一个字节的64位值 我希望这个解决方案在OS/编译器之间实现移植——最低限度支持GNU G+和Visual C++,以及Linux和Windows之间。显然,对于这两种平台,我假设处理器支持x86-64指令集 我通过Google找到了一些详细说明g++不兼容语法的片段。我承认我可能需

我有一个简单的(但性能关键的)C算法(嵌入C++中)来操作数据缓冲区。。。该算法“自然”使用64位big-endian寄存器值,我希望使用汇编程序对此进行优化,以获得对进位标志和BSWAP的直接访问,从而避免一次操作一个字节的64位值

<>我希望这个解决方案在OS/编译器之间实现移植——最低限度支持GNU G+和Visual C++,以及Linux和Windows之间。显然,对于这两种平台,我假设处理器支持x86-64指令集

我通过Google找到了一些详细说明g++不兼容语法的片段。我承认我可能需要用每种方言分别实现这个功能。我还没有找到足够详细的语法/功能文档来解决这个问题

我要找的是清晰的文档,详细说明了我可用的设施——包括MS和GNU工具集。虽然我在很多年前写过一些32位汇编程序,但我已经生疏了——我会从一份简洁的文档中受益,该文档详细说明了汇编级别的可用设施

另一个复杂的问题是,我想用Visual C++快照版2010编译Windows。我知道这是一个32位编译器,但我想知道,是否有可能将64位程序集嵌入其可执行文件中?在我计划编写代码的部分中,我只关心64位性能

谁能提供任何指针(请原谅双关语?)?< /p> 根据定义,C或C++中的ASM语句不是可移植的,特别是因为它们与特定的指令集绑定。特别是,如果您的汇编语句是针对x86的,则不要期望代码在ARM上运行

此外,即使在64位x86-64(即现代PC-s)这样的硬件平台上,不同的系统(例如Linux和Windows)也有不同的汇编程序语法和不同的调用约定。因此,您的代码应该有几个变体

如果使用GCC,它会为您提供许多内置函数,可以帮助您。而且可能(假设是最新的GCC,即4.6版本),它能够非常有效地优化您的功能


如果性能非常重要,如果你的系统有一个GPU(这是一个强大的图形卡),你可以考虑在OpenCL或CUDA中重新编码数值内核。

内嵌汇编程序并不是你的一种可能性:Wi64 Visual C编译器不支持<代码>asm编译过的文件。

为了让您了解前进道路上的障碍,这里有一个简单的内联汇编函数,使用两种方言。首先,Borland C++ +Builder版本(我认为这也是在MSVC++下编译):

现在,g++版本:

int BNASM_AddScalar (DWORD* result, DWORD x)
  {
  int carry = 0 ;
  asm volatile (
"    addl    %%ecx,(%%edx)\n"
"    adcl    $0,%%eax\n"    // Return the carry flag
: "+a"(carry)         // Output (and input): carry in eax
: "d"(result), "c"(x) // Input: result in edx and x in ecx
) ;
  return carry ;
  }
正如你所看到的,差别很大。他们周围没有路可走。它们来自我为32位环境编写的大型整数算术库


至于在32位可执行文件中嵌入64位指令,我认为这是禁止的。据我所知,32位可执行文件在32位模式下运行,任何64位指令都只会生成陷阱。

不幸的是,MSVC++不支持64位代码中的内联汇编,也不支持_;u emit。使用MSVC++时,您应该在单独的.asm文件中实现代码片段,并编译它们并将其与其余代码链接,或者采用如下脏方法(为32位代码实现,作为概念证明):


其余的都很简单。

有许多函数可用于交换端性,例如从BSD套接字:

uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
64位的可移植性较差:

unsigned __int64 _byteswap_uint64(unsigned __int64); // Visual C++
int64_t __builtin_bswap64 (int64_t x). // GCC

不要在标准C++中不能表达的时候诉诸汇编。

对不起,但是我相信当你需要一个便携代码时,把它放在C++代码中。在测试代码时会遇到很多问题。但是,对于32位和64位,它们是不同的可执行文件,因此您可以只使用#ifdef(ifdef)M_IX86。。。使用32位c代码#其他的使用您的64位代码#我还必须补充一点,现代编译器对代码进行了大量优化,我不知道这是否真的值得,在考虑将其移植到其他语言之前,您应该做一些性能测试。尝试MSVC,然后检查是否值得。我相信我已经找到了一种情况,访问BSWAP和carry标志将产生显著的好处。我很乐意实现多个版本(由预处理器指令保护),但我仍然需要建立可以在每个上下文中使用的语法?也许你需要一些东西。再看看汇编程序代码的几个变体是可以接受的。。。我需要的是很好的参考资料,描述我应该为每种语言使用的语法。我对CUDA和OpenCL都感兴趣-它们代表了未来潜在的增强功能。。。尽管我怀疑他们可能会被我的算法天生的非并行性所破坏。现在,我只想指出高效汇编级实现的优势。在32位可执行文件中禁止64位指令是有道理的,我想你是对的。我仍然可以只使用32位指令获得一些优势。到目前为止,您的示例在我的浏览中已经很熟悉了,您能给我指一下描述这些语法的好文档吗?64位指令在32位模式下通常被解释为不同的指令,不一定无效,但无论如何都可能导致崩溃。例如,REX前缀的编码方式与INC和DEC相同。@aSteve:GnuCompiler集合文档如下:。第6.41节和第6.42节是您想要的。不幸的是,文档是相当不可原谅的——你需要是一个GNU编译器编写者(我不是),或者你需要做很多实验(我做了)。这太肮脏了!(有趣,tho
unsigned char BswapData64[] =
{
  0x48, 0x0F, 0xC9, // bswap rcx
  0x48, 0x89, 0xC8, // mov   rax, rcx
  0xC3              // ret
};

unsigned long long (*Bswap64)(unsigned long long) =
  (unsigned long long (*)(unsigned long long))BswapData64;
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
unsigned __int64 _byteswap_uint64(unsigned __int64); // Visual C++
int64_t __builtin_bswap64 (int64_t x). // GCC