正如我们所知,汇编文件(.S)会在汇编之前进行预处理,但我发现在预处理之后,结果汇编文件中可能会有结构/函数原型,gnu如何处理这些原型?只是忽略了它?
例如,以下命令:
gcc -E -o tmp.result arch / x86 / boot / copy.S -Iinclude / -Iarch / x86 / include /
,生成的程序集文件(tmp.result)为:
# 1 "arch/x86/boot/copy.S"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "arch/x86/boot/copy.S"
# 11 "arch/x86/boot/copy.S"
# 1 "include/linux/linkage.h" 1
# 1 "include/linux/compiler.h" 1
# 5 "include/linux/linkage.h" 2
# 1 "include/linux/stringify.h" 1
# 6 "include/linux/linkage.h" 2
# 1 "include/linux/export.h" 1
# 26 "include/linux/export.h"
struct kernel_symbol
{
unsigned long value;
const char *name;
};
# 7 "include/linux/linkage.h" 2
# 1 "arch/x86/include/asm/linkage.h" 1
# 8 "include/linux/linkage.h" 2
# 12 "arch/x86/boot/copy.S" 2
.code16
.text
GLOBAL(memcpy)
pushw %si
pushw %di
movw %ax, %di
movw %dx, %si
pushw %cx
shrw $2, %cx
rep; movsl
popw %cx
andw $3, %cx
rep; movsb
popw %di
popw %si
retl
ENDPROC(memcpy)
但是在尝试组装此文件时:
as -o tmp.o tmp.result
产生以下错误:
include/linux/export.h: Assembler messages:
include/linux/export.h:26: Error: no such instruction: `struct kernel_symbol'
include/linux/export.h:27: Error: junk at end of line, first unrecognized character is `{'
include/linux/export.h:28: Error: no such instruction: `unsigned long value'
include/linux/export.h:29: Error: no such instruction: `const char *name'
include/linux/export.h:30: Error: junk at end of line, first unrecognized character is `}'
arch/x86/boot/copy.S:20: Error: invalid character '(' in mnemonic
arch/x86/boot/copy.S:34: Error: invalid character '(' in mnemonic
arch/x86/boot/copy.S:36: Error: invalid character '(' in mnemonic
arch/x86/boot/copy.S:49: Error: invalid character '(' in mnemonic
arch/x86/boot/copy.S:51: Error: invalid character '(' in mnemonic
arch/x86/boot/copy.S:58: Error: invalid character '(' in mnemonic
arch/x86/boot/copy.S:60: Error: invalid character '(' in mnemonic
arch/x86/boot/copy.S:67: Error: invalid character '(' in mnemonic
似乎汇编程序无法处理tmp.result中的结构。 Linux源代码(.S)如何通过组装?
答案 0 :(得分:4)
as
无法处理struct
和函数原型 - 它们只适用于C编译器,并且可以进入&#34;拉入&#34;在你的预处理错误。事实上,如果您查看提供struct
定义的标题,you'll see:
#ifndef __ASSEMBLY__
struct kernel_symbol
{
unsigned long value;
const char *name;
};
因此,上方的标题被认为包含在汇编和C中,但您没有定义__ASSEMBLY__
来告诉它您将其包含在汇编文件。
有趣的是,gcc确实有一个内置的__ASSEMBLER__
预定义宏来区分汇编文件或C文件中的包含,但似乎内核does not use it for historical reasons依赖于手动定义{{ 1}}预处理汇编文件时。
长话短说:要从预处理器获得正确的输出,你应该做类似的事情
__ASSEMBLY__
(免责声明:我并不完全熟悉内核构建过程,上面的行可能有包含路径的其他问题,或者正确的方法是调用gcc -E -D__ASSEMBLY__ -o tmp.result arch/x86/boot/copy.S -Iinclude/ -Iarch/x86/include/
而不是{{1或者其他 - 我不知道)