我们知道,汇编文件(.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)
Run Code Online (Sandbox Code Playgroud)
但在尝试组装此文件时:
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
Run Code Online (Sandbox Code Playgroud)
似乎汇编程序无法处理tmp.result中的结构.Linux源代码(.S)如何通过组装?
as无法处理struct和函数原型 - 它们仅适用于 C 编译器,并且在您的预处理中被错误地“拉入”。事实上,如果您查看提供该struct定义的标题,您会看到:
#ifndef __ASSEMBLY__
struct kernel_symbol
{
unsigned long value;
const char *name;
};
Run Code Online (Sandbox Code Playgroud)
因此,上面的头文件被认为同时包含在程序集和 C 中,但是您没有定义__ASSEMBLY__来告诉它您将它包含到程序集文件中。
有趣的是,gcc 确实有一个内置的__ASSEMBLER__预定义宏来区分包含在汇编文件中还是 C 文件中,但内核似乎由于历史原因没有使用它,而是在__ASSEMBLY__预处理汇编文件时依靠手动定义。
长话短说:要从预处理器获得正确的输出,您应该执行以下操作
gcc -E -D__ASSEMBLY__ -o tmp.result arch/x86/boot/copy.S -Iinclude/ -Iarch/x86/include/
Run Code Online (Sandbox Code Playgroud)
(免责声明:我对内核构建过程并不完全熟悉,上面的行可能有包含路径的其他问题,或者正确的方法可能是调用cpp而不是调用gcc或其他什么 - 我不知道)