.s文件、.S文件和.o文件的区别

本文详细解析了.s与.S文件的区别,前者是汇编语言源程序,不再进行预处理;后者则会进行预处理与汇编。同时,介绍了.o文件的概念,它是编译但未链接的文件,包含函数入口标记,需链接成可执行文件。

s文件和.o文件的区别

.s 汇编语言源程序;  操作: 汇编

.S汇编语言源程序;  操作: 预处理 + 汇编

.s结尾文件:

小写的 s文件,在后期阶段不会再进行预处理操作了,所以我们不能在其内写上预处理语句。

一般是 .c 文件经过汇编器处理后的输出。 如 GCC 编译器就可以指定 -S 选项进行输出,且是经过预处理器处理后的了。

例如:gcc -S test.c-----生成.s结尾的文件,打开为汇编代码

 

.S结尾的文件:

大写的 S 文件,还会进行预处理、汇编等操作,所以我们可以在这里面加入预处理的命令。编译器在编译汇编大 S 文件之前会进行预处理操作。

.o文件

只编译不链接形成.o文件。里面包含了对各个函数的入口标记,描述,当程序要执行时还需要链接(link).链接就是把多个.o文件链成一个可执行文件。如 GCC 编译器就可以指定 -c选项进行输出。打开是乱码。

例如:gcc -c test.c-------结果生成.o文件。


--------------------- 
作者:青听_Hao 
来源:优快云 
原文:https://blog.youkuaiyun.com/hao745580264_dawei/article/details/80751683 
版权声明:本文为博主原创文章,转载请附上博文链接!

<think>我们想要编写一个Makefile来自动编译指定目录下的所有C源文件.c)汇编源文件.s或.S)。我们将使用GCC编译器(或交叉编译器)来编译这些文件,并将它们链接成一个可执行文件。 步骤: 1. 定义编译器、编译选项、链接选项等变量。 2. 使用通配符获取所有源文件.c.S文件)。 3. 将源文件列表转换为目标文件列表(.o文件)。 4. 定义默认目标(通常是最终的可执行文件),并指定其依赖关系。 5. 定义模式规则来编译.c文件.S文件。 6. 定义清理规则。 注意: - 汇编文件通常有两种扩展名:小写的.s(不经过预处理的汇编)大写的.S(需要预处理的汇编)。我们这里考虑.S文件(需要预处理的汇编).c文件。 - 我们假设所有源文件都在同一个目录下。 以下是一个示例Makefile: ```makefile # 定义编译器,如果是交叉编译,则替换为交叉编译器,例如:arm-none-eabi-gcc CC = gcc # 编译选项 CFLAGS = -Wall -Wextra -O2 # 汇编选项(对于.S文件,需要预处理编译) ASFLAGS = -Wall -O2 # 链接选项 LDFLAGS = # 源文件目录(当前目录) SRC_DIR = . # 获取所有.c.S文件 C_SOURCES = $(wildcard $(SRC_DIR)/*.c) ASM_SOURCES = $(wildcard $(SRC_DIR)/*.S) # 生成目标文件列表(.o文件) C_OBJS = $(C_SOURCES:.c=.o) ASM_OBJS = $(ASM_SOURCES:.S=.o) # 所有目标文件 OBJS = $(C_OBJS) $(ASM_OBJS) # 最终可执行文件名 TARGET = app # 默认目标:生成可执行文件 $(TARGET): $(OBJS) $(CC) $(LDFLAGS) -o $@ $^ # 模式规则:编译.c文件.o文件 %.o: %.c $(CC) $(CFLAGS) -c $< -o $@ # 模式规则:编译.S文件.o文件 %.o: %.S $(CC) $(ASFLAGS) -c $< -o $@ # 清理规则 .PHONY: clean clean: rm -f $(OBJS) $(TARGET) ``` 解释: 1. `CC`:定义C编译器,如果是交叉编译,可以修改为交叉编译器,比如`arm-none-eabi-gcc`。 2. `CFLAGS`:C编译选项,例如开启所有警告优化。 3. `ASFLAGS`:汇编编译选项,注意对于.S文件(需要预处理的汇编)我们使用C编译器来编译(因为需要预处理),所以这里使用`$(CC)``$(ASFLAGS)`。 4. 使用`wildcard`函数获取当前目录下所有的.c.S文件。 5. 使用替换函数将源文件列表转换为目标文件列表(.o文件)。 6. 默认目标`$(TARGET)`依赖于所有的目标文件(`$(OBJS)`),链接这些目标文件生成可执行文件。 7. 两个模式规则: - 第一个模式规则:如何从.c文件生成.o文件。 - 第二个模式规则:如何从.S文件生成.o文件。 8. 清理规则:删除所有中间文件可执行文件。使用`.PHONY`声明`clean`为伪目标。 注意:如果汇编文件是小写的.s(不需要预处理),那么我们可以使用`as`汇编器,但为了统一,我们这里使用相同的编译器来处理.S文件(它会自动调用预处理器汇编器)。对于.s文件,如果不需要预处理,我们可以单独写一条规则: 如果需要处理.s文件(不经过预处理),可以添加: ```makefile %.o: %.s $(AS) $(ASFLAGS) -c $< -o $@ ``` 其中`AS`可以定义为`as`(GNU汇编器)。但是,为了简单起见,我们通常将汇编文件写成.S(大写)以便进行预处理(例如使用条件编译等),然后统一用gcc编译。 如果项目中同时存在.S.s文件,那么需要分别处理。但通常建议统一使用.S文件(需要预处理)或者.s文件(不需要预处理)。这里我们只处理了.S文件。 如果希望同时支持.S.s,可以修改: ```makefile ASM_SOURCES = $(wildcard $(SRC_DIR)/*.S) $(wildcard $(SRC_DIR)/*.s) ``` 然后分别写规则: ```makefile # 编译.S文件(需要预处理) %.o: %.S $(CC) $(ASFLAGS) -c $< -o $@ # 编译.s文件(不需要预处理) %.o: %.s $(AS) $(ASFLAGS) -c $< -o $@ ``` 其中`AS`可以定义为`as`,`ASFLAGS`可以设置为汇编器选项(例如:`-march=armv7-a`等)。 但是,在嵌入式开发中,我们通常使用交叉编译器,并且交叉编译器会提供统一的编译接口,通常使用`$(CC)`来编译汇编文件(无论是.S还是.s)也是可以的。例如,对于ARM,`arm-none-eabi-gcc`可以处理.s.S,它会根据扩展名自动决定是否进行预处理。 因此,我们可以简化,只使用一条规则来处理所有汇编文件(包括.S.s),但需要将它们都视为需要预处理的?实际上,gcc对于.s文件默认不会进行预处理,除非你指定了`-x assembler-with-cpp`选项。所以,为了区分,最好还是分开写。 不过,为了简单,我们可以将所有的汇编文件都视为需要预处理的(即使用.S),或者都视为不需要预处理的(即使用.s)。这样,我们就可以只用一条规则。 这里,我们假设项目中的汇编文件都是.S(需要预处理)类型,所以我们只使用一条规则。 如果项目中有.s文件,那么我们可以修改规则: ```makefile # 处理.S.s文件(使用相同的规则,但注意:gcc对.s文件不会进行预处理,除非指定选项) # 因此,我们分开处理 # 对于.S文件(需要预处理) %.o: %.S $(CC) $(ASFLAGS) -c $< -o $@ # 对于.s文件(不需要预处理) %.o: %.s $(CC) -c $< -o $@ # 这里不加预处理选项,或者使用汇编器as ``` 但是,为了避免复杂化,建议统一汇编文件的扩展名。 因此,我们回到最初的Makefile,只处理.c.S文件。 另外,如果源文件分布在多个目录,我们需要更复杂的处理(例如指定搜索路径)。但这里只考虑当前目录。 最后,执行`make`即可编译,`make clean`即可清理。 注意:如果使用交叉编译,需要将`CC`变量设置为交叉编译器,例如`CC = arm-none-eabi-gcc`。 如果编译的是嵌入式系统程序(无操作系统),可能需要添加额外的链接脚本链接选项,例如: ```makefile LDFLAGS = -T link.ld -nostartfiles ``` 这取决于具体的项目需求。 以上Makefile已经可以满足自动编译当前目录下所有.c.S文件的需求。</think>下面是一个完整的Makefile模板,用于自动编译指定目录下的所有C汇编文件(支持`.c``.s/.S`扩展名): ```makefile # 编译器设置 CROSS_COMPILE ?= CC = $(CROSS_COMPILE)gcc AS = $(CROSS_COMPILE)gcc LD = $(CROSS_COMPILE)gcc # 编译选项 CFLAGS = -Wall -Wextra -O2 ASFLAGS = -c LDFLAGS = # 目录设置 SRC_DIR = . BUILD_DIR = build # 自动获取所有源文件 C_SOURCES = $(wildcard $(SRC_DIR)/*.c) ASM_SOURCES = $(wildcard $(SRC_DIR)/*.s $(SRC_DIR)/*.S) # 生成目标文件列表 C_OBJS = $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%.o,$(C_SOURCES)) ASM_OBJS = $(patsubst $(SRC_DIR)/%.s,$(BUILD_DIR)/%.o,\ $(patsubst $(SRC_DIR)/%.S,$(BUILD_DIR)/%.o,$(ASM_SOURCES))) OBJS = $(C_OBJS) $(ASM_OBJS) # 最终目标 TARGET = myapp # 默认目标 all: $(BUILD_DIR) $(TARGET) # 创建构建目录 $(BUILD_DIR): mkdir -p $(BUILD_DIR) # 链接目标文件生成可执行文件 $(TARGET): $(OBJS) $(LD) $(LDFLAGS) -o $@ $^ # 编译C源文件 $(BUILD_DIR)/%.o: $(SRC_DIR)/%.c $(CC) $(CFLAGS) -c $< -o $@ # 编译汇编源文件(.s.S) $(BUILD_DIR)/%.o: $(SRC_DIR)/%.s $(AS) $(ASFLAGS) $< -o $@ $(BUILD_DIR)/%.o: $(SRC_DIR)/%.S $(AS) $(ASFLAGS) $< -o $@ # 清理 .PHONY: clean clean: rm -rf $(BUILD_DIR) $(TARGET) # 伪目标声明 .PHONY: all clean ``` ### 关键功能说明: 1. **自动文件发现**: - `wildcard`函数自动查找所有`.c``.s/.S`文件[^4] - `patsubst`函数自动生成目标文件路径 2. **目录管理**: - 创建专门的`build`目录存放中间文件 - 源文件构建文件分离,保持项目整洁 3. **多文件类型支持**: - 分别处理C文件(`.c`)汇编文件(`.s/.S`) - 汇编文件使用`-c`选项确保正确编译[^2] 4. **交叉编译支持**: - 通过`CROSS_COMPILE`变量指定交叉编译前缀 - 例如:`make CROSS_COMPILE=arm-none-eabi-` 5. **伪目标声明**: - `.PHONY`确保`clean`目标总是执行[^5] - 避免与同名文件冲突 ### 使用示例: 1. **基本编译**: ```bash make ``` 2. **交叉编译**: ```bash make CROSS_COMPILE=arm-none-eabi- ``` 3. **清理构建**: ```bash make clean ``` 4. **查看文件列表**: ```bash make -n # 显示将执行的操作但不实际运行 ``` ### 高级定制选项: 1. **添加包含路径**: ```makefile CFLAGS += -Iinclude ``` 2. **定义宏**: ```makefile CFLAGS += -DDEBUG ``` 3. **优化级别**: ```makefile CFLAGS += -O3 # 最高优化 ``` 4. **链接库**: ```makefile LDFLAGS += -lm # 链接数学库 ``` 5. **多目录支持**: ```makefile VPATH = src:lib # 添加多个源文件目录 ``` 这个Makefile会自动发现并编译当前目录下所有C汇编文件,生成可执行文件并管理中间文件[^1][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值