CMake重复汇编问题:汇编文件被两次汇编而非用objcopy生成最终二进制
CMake重复汇编NASM二进制文件的问题原因与解决方法
问题原因
你在NASM编译时使用了-f bin参数,这会直接生成最终的原始二进制镜像(也就是你说的512字节可启动文件),但CMake的ADD_EXECUTABLE逻辑是为常规可执行文件设计的:它会先将源文件编译为目标文件(.obj/.o),再调用链接器生成最终可执行文件。
由于你的项目指定了ASM_NASM作为唯一语言,CMake错误地认为“链接”步骤也需要用NASM来完成,于是把第一次生成的二进制文件当成了需要再次汇编的源文件,导致第二次调用NASM处理非汇编文件,最终输出0字节的无效文件和警告。
解决方法
方案1:通过ELF目标文件生成二进制(适合需要链接其他代码的场景)
先让NASM生成ELF格式的目标文件,让CMake完成正常的链接流程,再用objcopy提取纯二进制镜像:
CMAKE_MINIMUM_REQUIRED(VERSION 3.3.2) PROJECT(bootloader ASM_NASM) # 配置NASM生成ELF64目标文件(根据你的架构调整,比如elf32对应x86) SET(CMAKE_ASM_NASM_OBJECT_FORMAT elf64) SET(CMAKE_ASM_NASM_FLAGS "-g -F dwarf") ADD_EXECUTABLE(bootloader ${CMAKE_CURRENT_LIST_DIR}/arch/${ARCH}/boot.asm ) # 编译完成后用objcopy生成原始二进制文件 ADD_CUSTOM_COMMAND(TARGET bootloader POST_BUILD COMMAND ${CMAKE_OBJCOPY} -O binary $<TARGET_FILE:bootloader> ${CMAKE_BINARY_DIR}/bootloader.bin COMMENT "Generating raw binary bootloader image..." )
方案2:直接自定义命令生成二进制(适合纯汇编的MBR/bootloader)
跳过CMake的ADD_EXECUTABLE默认流程,直接调用NASM生成二进制文件:
CMAKE_MINIMUM_REQUIRED(VERSION 3.3.2) PROJECT(bootloader ASM_NASM) # 定义源文件和输出文件路径 SET(BOOT_ASM_SOURCE ${CMAKE_CURRENT_LIST_DIR}/arch/${ARCH}/boot.asm) SET(BOOT_BINARY_OUTPUT ${CMAKE_BINARY_DIR}/bootloader.bin) # 自定义汇编命令 ADD_CUSTOM_COMMAND( OUTPUT ${BOOT_BINARY_OUTPUT} COMMAND nasm -f bin -o ${BOOT_BINARY_OUTPUT} ${BOOT_ASM_SOURCE} DEPENDS ${BOOT_ASM_SOURCE} COMMENT "Assembling bootloader to raw binary..." ) # 创建自定义目标,让构建系统可以直接触发这个任务 ADD_CUSTOM_TARGET(bootloader ALL DEPENDS ${BOOT_BINARY_OUTPUT})
说明
- 方案1适合需要整合C/C++代码的复杂bootloader,保留CMake的依赖管理和链接能力。
- 方案2更轻量,适合纯汇编编写的MBR等不需要链接的启动代码,完全避开CMake的可执行文件构建逻辑。
内容的提问来源于stack exchange,提问作者SelflessPotato
相关产品推荐
相关产品推荐

