可以包含以下源代码:
extern "C"
{
#include "src.c"
}
#include "src.cpp"
是否可以为.asm(程序集)文件执行此操作?
答案 0 :(得分:1)
TL:DR 没有大多数编译器,除非你将asm源文件转换成可以进入全局范围内的asm
语句的内容。然后肯定,但为什么要打扰;分别建立asm通常要好得多。
GNU C inline-asm语法允许您将任意程序集放在全局范围内,以便与编译器生成的asm一起组装。在任何C / C ++函数之外使用asm("instructions and assembler directives ...");
。
但是要在包含.S
文件(GAS语法asm源)时使其工作,您需要在C ++源代码中的双引号内获取.S
的预处理内容。这是不可能的:C/C++, can you #include a file into a string literal?
如果你能写出像这样的东西
int foo () { return 0; }
asm ("#include \"src.S\" "); // doesn't work
以实际包含src.S
内容的方式,它会起作用。如果你真的使用它,compiler's asm output will be:
.file "example.cpp"
.text
.Ltext0:
#APP
#include "src.S"
#NO_APP
# omitted some .directives
foo:
xorl %eax, %eax
ret
#
is the comment character in GNU as
syntax for x86,因此汇编程序输入中的#include "src.S"
只被视为注释!
gcc foo.S
在foo.S
上运行C预处理器(生成foo.s
),然后将其提供给汇编程序。但这不会发生在编译器生成的asm输出上;在编译之前,只有C / C ++源是通过CPP提供的。
你可以编写一个asm源文件,用双引号包装每一行,就像你在asm
语句体内写的一样。
例如,bar.inline-asm
可能是
".p2align 4 \n\t"
".globl bar \n\t"
".type bar, @function \n\t"
"bar: \n\t"
" lea (%rdi,%rsi,2), %eax \n\t"
" ret \n\t"
".size bar, .-bar \n\t"
(请注意,这是GNU C Basic ASM,因此我们不需要将%
字符加倍。)
使用此src.c
,我们可以对其进行测试:
// extern "C" // if this is in C++.
int bar(int a, int b);
asm(
#include "bar.inline-asm"
);
int main(void) {
return bar(2, 4);
}
我对此进行了测试,并且有效:
peter@volta:~/src/SO$ gcc -Wall -O2 include-asm.c
peter@volta:~/src/SO$ ./a.out; echo $?
10
# correct result for 2 + 4*2
$ disas a.out # alias for objdump -drwC -Mintel
...
0000000000000530 <main>:
530: be 04 00 00 00 mov esi,0x4
535: bf 02 00 00 00 mov edi,0x2
53a: e9 11 01 00 00 jmp 650 <bar> # optimized tail-call to bar()
53f: 90 nop
...
0000000000000650 <bar>:
650: 8d 04 77 lea eax,[rdi+rsi*2]
653: c3 ret
654: 66 2e 0f 1f 84 00 00 00 00 00 nop WORD PTR cs:[rax+rax*1+0x0]
65e: 66 90 xchg ax,ax
显然,在这种情况下,这样做没有任何优势,只需要gcc -O2 foo.c asm.S
来构建最终链接在一起的单独目标文件。
它不会使名称变得更容易,也就是说它不会简化_bar
(Windows)与bar
(Linux)的情况。 (如果您使用的是x86 asm,请参阅Agner Fog's calling conventions PDF以及他的asm优化指南。)