我在make编译的时候一个汇编文件boot.S报错,如下图所示,但是当我单独使用gcc命令编译却一切正常(同样的参数),请问这是怎么回事?如何解决?
makefile如下:
toolchain := riscv64-unknown-elf-
GCC := $(toolchain)gcc
AS := $(toolchain)as
LD := $(toolchain)ld
OBJCOPY :=$(toolchain)objcopy
COPS := -g -O0 -Wall -nostdlib -nostdinc -Iinclude -mcmodel=medany -fno-PIE -fomit-frame-pointer -Wno-builtin-declaration-mismatch -ggdb -g
all: system
$(OBJCOPY) -O binary system kernel.bin
system: ./kernel/main.o ./kernel/boot.o ./kernel/urat.o
$(LD) -z muldefs -T ./kernel/linker.ld -o system ./kernel/main.o ./kernel/boot.o ./kernel/urat.o
main.o: ./kernel/main.c
$(GCC) $(COPS) -c ./kernel/main.c
boot.o: ./kernel/boot.S
$(GCC) $(COPS) -c ./kernel/boot.S
urat.o: ./kernel/urat.c
$(GCC) $(COPS) -c ./kernel/urat.c
clean:
rm -rf ./kernel/*.o
rm -rf system kernel.bin
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
根据错误提示信息可以看出,make
编译时出现了以下错误:
./kernel/boot.S: Assembler messages:
./kernel/boot.S:7: Error: illegal instruction
但是当使用 gcc
命令单独编译时却没有这个问题。这很可能是因为 make
与 gcc
在编译时的参数不同导致的。
在你的 Makefile
中,boot.o
的编译语句为:
$(GCC) $(COPS) -c ./kernel/boot.S
其中,$(COPS)
包含了一些编译参数,可能是这些参数导致了问题。建议一步一步进行调试。
可以先将 -c
参数去掉,将 boot.S
编译为汇编文件,如下所示:
$(AS) -o ./kernel/boot.o ./kernel/boot.S
如果这一步没有问题,可以加上 -v
参数来查看 gcc
在编译时默认使用的参数,再与 $(COPS)
中的参数进行比对,看看是否有冲突。
最后,你可以尝试在 $(COPS)
中逐个排除参数,重新编译 boot.o
文件,找出导致问题的参数。
以下是经过修改的 Makefile
:
toolchain := riscv64-unknown-elf-
GCC := $(toolchain)gcc
AS := $(toolchain)as
LD := $(toolchain)ld
OBJCOPY :=$(toolchain)objcopy
# COPS := -g -O0 -Wall -nostdlib -nostdinc -Iinclude -mcmodel=medany -fno-PIE -fomit-frame-pointer -Wno-builtin-declaration-mismatch -ggdb -g
COPS := -g -O0 -Wall -mcmodel=medany -fno-PIE -fomit-frame-pointer
all: system
$(OBJCOPY) -O binary system kernel.bin
system: ./kernel/main.o ./kernel/boot.o ./kernel/urat.o
$(LD) -z muldefs -T ./kernel/linker.ld -o system ./kernel/main.o ./kernel/boot.o ./kernel/urat.o
main.o: ./kernel/main.c
$(GCC) $(COPS) -c ./kernel/main.c
boot.o: ./kernel/boot.S
$(AS) -o ./kernel/boot.o ./kernel/boot.S
urat.o: ./kernel/urat.c
$(GCC) $(COPS) -c ./kernel/urat.c
clean:
rm -rf ./kernel/*.o
rm -rf system kernel.bin
注意,我在 $(COPS)
中注释掉了 -nostdlib
和 -nostdinc
参数,这两个参数会排除标准库和标准头文件,这对你的项目可能不是必须的。
如果我的回答解决了您的问题,请采纳!
参考GPT的内容和自己的思路,根据错误信息,可以看到在 kernel/boot.S 中存在汇编指令的问题,该汇编指令可能在GCC版本和assembler版本之间存在差异,因此需要进一步了解问题所在。
一种可能是,GCC和AS之间的默认指令集不同,导致在汇编boot.S时出现了错误。你可以通过在Makefile中指定AS的版本,例如:
AS := $(toolchain)as -march=rv64imafd
另一种可能是,GCC和AS在默认情况下使用不同的ABI。可以通过在Makefile中指定ABI来解决此问题,例如:
COPS := -g -O0 -Wall -nostdlib -nostdinc -Iinclude -mcmodel=medany -fno-PIE -fomit-frame-pointer -Wno-builtin-declaration-mismatch -ggdb -g -mabi=lp64
你可以尝试在Makefile中添加上述选项,重新运行make,看看能否解决问题。如果还有其他问题,请检查汇编指令是否与当前使用的指令集和ABI兼容。
回答不易,还请能采纳!!!
“Devil组”引证GPT后的撰写:
为boot.S使用GCC作为汇编器,这是不正确的。汇编器应该使用as命令而不是GCC。因此,要将以下行:
boot.o: ./kernel/boot.S
$(GCC) $(COPS) -c ./kernel/boot.S
更改为:
boot.o: ./kernel/boot.S
$(AS) $(COPS) -c ./kernel/boot.S
这将确保使用正确的汇编器编译汇编文件,并且应该解决您遇到的问题。
此外,您需要修复kernel/main.c中的函数调用警告,即添加头文件以声明uart函数。如果您使用的是uart.h文件,则可以在文件开头添加以下行:
#include "uart.h"
没有该文件,则需要创建它并将uart函数声明添加到其中,例如:
#ifndef __UART_H__
#define __UART_H__
void uart_init();
void uart_send_string(const char* str);
#endif /* __UART_H__ */