使用Clang编译内联intel语法汇编的C/C++项目

我们在编写C/C++代码时,如果在有较高性能需求的时候,可以使用汇编代码来编写相应的函数,C/C++直接调用即可。汇编的语法格式有两种,一种是我们在Windows下常见的Intel的语法格式;另一种是GCC下使用的AT&T格式的语法,这种语法对我们经常使用Windows或者从Windows开始学习编程的开发人员来说会感觉很晦涩。
我们看看MS方式的内联汇编写法:

	__asm
	{
		push rax
		xor rax, rax
		pop rax
	}

再看看,AT&T的写法:

__asm("push %rax");
__asm("xor %rax, %rax");
__asm("pop %rax");

C/C++提供了外联与内联两种方式来与汇编代码进行交互,不过内联的方式需要编译器的支持。在X86下,微软的C/C++编译器是支持内联Intel语法格式的汇编代码的,但是在X64下就不再支持了。GCC是在X86与X64下都支持内联AT&T语法格式的汇编代码。

如果我们要把Windows下的带有内联Intel语法格式的汇编在Linux下使用GCC进行编译,就需要把内联汇编的格式改为AT&T的语法格式,这是一件很痛苦的事情,目前还不清楚是否有编译参数可以不修改任何代码支持Intel的语法格式。而Clang编译器可以做到,可以直接加参数:

-fms-extensions

或者

-fasm-blocks

即可编译,不需要任何代码修改。如果只需要支持MS的内联汇编功能,建议使用-fasm-blocks参数,如果还需要其它MS的扩展功能才使用-fms-extensions。-fms-extensions参数在命令行帮助中有列出,而-fasm-blocks参数未列出,是看源码得知的,参见:ParseStmtAsm.cpp中的

/// ParseMicrosoftAsmStatement. When -fms-extensions/-fasm-blocks is enabled,
/// this routine is called to collect the tokens for an MS asm statement.
///
/// [MS]  ms-asm-statement:
///         ms-asm-block
///         ms-asm-block ms-asm-statement
///
/// [MS]  ms-asm-block:
///         '__asm' ms-asm-line '\n'
///         '__asm' '{' ms-asm-instruction-block[opt] '}' ';'[opt]
///
/// [MS]  ms-asm-instruction-block
///         ms-asm-line
///         ms-asm-line '\n' ms-asm-instruction-block
///
StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
  SourceManager &SrcMgr = PP.getSourceManager();
  SourceLocation EndLoc = AsmLoc;
  SmallVector<Token, 4> AsmToks;

clang默认是直接支持AT&T格式的内联汇编的,所以在加了上述参数后,也可以使用AT&T格式的汇编,即两种语法格式混合使用。
如:

int main(int argc, char *argv[])
{
	__asm
	{
		push rax
		xor rax, rax
		pop rax
	}

	__asm("push %rax");
	__asm("xor %rax, %rax");
	__asm("pop %rax");

	return 0;
}

一样可以通过clang编译,运行反汇编:
使用Clang编译内联intel语法汇编的C/C++项目_第1张图片

该方法在LLVM Clang的Windows版本即clang-cl、Mingw下的clang以及Linux下的clang下编译通过,clang-cl本身就是兼容MS的cl的,所以不添加任何参数,直接支持MS方式的内联汇编。

你可能感兴趣的:(#,汇编,跨平台,LLVM/Clang,clang,内联汇编,intel,C,C++)