在汇编文件中包含头文件
Including header file in assembly file
我试图将包含宏的头文件包含到我的主程序集文件中,但编译失败。
下面是我的main.S
文件
#include "common.h"
BEGIN
mov [=10=]x0E40, %ax
int [=10=]x10
hlt
下面是我的 common.h
文件:
.macro BEGIN
LOCAL after_locals
.code16
cli
ljmp [=11=], f
1:
xor %ax, %ax
/* We must zero %ds for any data access. */
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %bp
/* Automatically disables interrupts until the end of the next instruction. */
mov %ax, %ss
/* We should set SP because BIOS calls may depend on that. TODO confirm. */
mov %bp, %sp
/* Store the initial dl to load stage 2 later on. */
mov %dl, initial_dl
jmp after_locals
initial_dl: .byte 0
after_locals:
.endm
两个文件都在同一目录中。当我进行编译时:
$ as --32 -o main.o main.S
main.S: Assembler messages:
main.S:2: Error: no such instruction: `begin'
我错过了什么?我做了一些研究并在 SO 中得到了 ,但它没有帮助。请帮忙。
$ as --32 -o main.o main.S
as
只是一个 assembler,它将汇编源代码转换为目标代码。它不 运行 应该扩展 #include
.
的 C 预处理器
(#
是 x86 的 GAS 语法中的注释字符,因此如果该行被 assembler 看到而不是被 CPP 替换,则该行被视为注释)
你能做什么:
- 使用
gcc
到assemble,加上适当的文件后缀(.S
或.sx
),它会运行在[=72之前的C预处理器=]宁assembler。
- 添加
-v
以查看 gcc
调用了哪些命令。
- 如果您的来源有不同的后缀,您可以
-x assembler-with-cpp source.asm
。
- 如果要查看预处理后的中间结果,请添加
-save-temps
。这将使用预处理后的源写入一个 .s
文件。
- 如果您想将命令行选项传递给
as
,您可以例如 -Wa,--32
。但是,在本例中,最好使用编译器驱动程序理解的选项,如 -m32
或 -m16
。驱动程序知道这些选项,例如,它还会在链接时提供适当的选项,前提是您使用 gcc -m32 ...
进行链接,如下所述。
- 使用
.include
assembler 指令,它由 assembler 本身处理,而不是 C 预处理器。
注意: 在情况 1 中,通过 -I path
添加包含搜索路径可能无法按预期工作:编译器驱动程序(gcc
在这个case) 将仅在 assembler 的命令行中添加 -I path
如果它知道它是 GNU assembler。当编译器由配置标志 --with-gnu-as
.
配置时,您可以知道这一点
注意:链接也类似。您可能不想调用链接器(手动调用 ld
),除非您正在制作静态可执行文件或平面二进制文件;如果您要在主机系统上为 运行 创建普通可执行文件,请改用 gcc
或 g++
。它将添加链接所需的许多选项,如 multilib 路径、搜索路径等,您不想手动 fiddle。
(int [=34=]x10
是一个 16 位的 BIOS 调用,但它在现代主流 OS 下不起作用,只能在 DOS 或遗留 BIOS 引导程序。)
如果您的头文件只是汇编,则在 main.S 中包含 .include "file"
指令。但是这种做法会将代码插入到它包含的位置。
我试图将包含宏的头文件包含到我的主程序集文件中,但编译失败。
下面是我的main.S
文件
#include "common.h"
BEGIN
mov [=10=]x0E40, %ax
int [=10=]x10
hlt
下面是我的 common.h
文件:
.macro BEGIN
LOCAL after_locals
.code16
cli
ljmp [=11=], f
1:
xor %ax, %ax
/* We must zero %ds for any data access. */
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %bp
/* Automatically disables interrupts until the end of the next instruction. */
mov %ax, %ss
/* We should set SP because BIOS calls may depend on that. TODO confirm. */
mov %bp, %sp
/* Store the initial dl to load stage 2 later on. */
mov %dl, initial_dl
jmp after_locals
initial_dl: .byte 0
after_locals:
.endm
两个文件都在同一目录中。当我进行编译时:
$ as --32 -o main.o main.S
main.S: Assembler messages:
main.S:2: Error: no such instruction: `begin'
我错过了什么?我做了一些研究并在 SO 中得到了
$ as --32 -o main.o main.S
as
只是一个 assembler,它将汇编源代码转换为目标代码。它不 运行 应该扩展 #include
.
(#
是 x86 的 GAS 语法中的注释字符,因此如果该行被 assembler 看到而不是被 CPP 替换,则该行被视为注释)
你能做什么:
- 使用
gcc
到assemble,加上适当的文件后缀(.S
或.sx
),它会运行在[=72之前的C预处理器=]宁assembler。- 添加
-v
以查看gcc
调用了哪些命令。 - 如果您的来源有不同的后缀,您可以
-x assembler-with-cpp source.asm
。 - 如果要查看预处理后的中间结果,请添加
-save-temps
。这将使用预处理后的源写入一个.s
文件。 - 如果您想将命令行选项传递给
as
,您可以例如-Wa,--32
。但是,在本例中,最好使用编译器驱动程序理解的选项,如-m32
或-m16
。驱动程序知道这些选项,例如,它还会在链接时提供适当的选项,前提是您使用gcc -m32 ...
进行链接,如下所述。
- 添加
- 使用
.include
assembler 指令,它由 assembler 本身处理,而不是 C 预处理器。
注意: 在情况 1 中,通过 -I path
添加包含搜索路径可能无法按预期工作:编译器驱动程序(gcc
在这个case) 将仅在 assembler 的命令行中添加 -I path
如果它知道它是 GNU assembler。当编译器由配置标志 --with-gnu-as
.
注意:链接也类似。您可能不想调用链接器(手动调用 ld
),除非您正在制作静态可执行文件或平面二进制文件;如果您要在主机系统上为 运行 创建普通可执行文件,请改用 gcc
或 g++
。它将添加链接所需的许多选项,如 multilib 路径、搜索路径等,您不想手动 fiddle。
(int [=34=]x10
是一个 16 位的 BIOS 调用,但它在现代主流 OS 下不起作用,只能在 DOS 或遗留 BIOS 引导程序。)
如果您的头文件只是汇编,则在 main.S 中包含 .include "file"
指令。但是这种做法会将代码插入到它包含的位置。