GNU可以作为汇编文件(.s)中的流程结构和函数原型吗?

Kin*_*wah 5 assembly gcc

我们知道,汇编文件(.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)如何通过组装?

Mat*_*lia 5

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或其他什么 - 我不知道)