【发布时间】:2017-04-14 12:56:20
【问题描述】:
我已经写了 2-3 年的 C 语言,最近开始学习汇编,但由于我使用的是 Windows,所以我以前从来不需要使用 make 文件,因为我刚刚使用了 Visual Studio。我正在尝试使用 Cygwin 和 i686 交叉编译器来编译 c 和汇编文件,然后将它们链接到代表我的操作系统的二进制文件中。我是制作文件的新手,所以我不知道如何正确执行此操作。这就是我目前对Makefile 的了解:
CC = i686-elf-gcc
CC_FLAGS = -c -std=gnu99 -ffreestanding -O2 -Wall -Wextra -I./include
AS = i686-elf-as
LD = i686-elf-gcc -T linker.ld -o myos.bin
LD_FLAGS = -ffreestanding -O2 -nostdlib -lgcc
O_FILES = $(wildcard src/*.o)
all: $(O_FILES)
$(LD) $(LD_FLAGS) $(O_FILES)
src/%.o: src/%.c
$(CC) $(CC_FLAGS) -o $@ $<
src/%.o: src/%.asm
$(AS) -o $@ $<
我收到一条错误消息,指出链接器找不到入口符号_start,因此显然没有编译任何内容。我该如何解决这个问题?
将_start定义为入口点的src/linker.ld文件是:
ENTRY(_start)
SECTIONS
{
. = 1M;
.text BLOCK(4K) : ALIGN(4K)
{
*(.multiboot)
*(.text)
}
.rodata BLOCK(4K) : ALIGN(4K)
{
*(.rodata)
}
.data BLOCK(4K) : ALIGN(4K)
{
*(.data)
}
.bss BLOCK(4K) : ALIGN(4K)
{
*(COMMON)
*(.bss)
}
}
我使用的定义我的_start 标签的src/boot.asm文件是:
# Declare constants for the multiboot header.
.set ALIGN, 1<<0 # align loaded modules on page boundaries
.set MEMINFO, 1<<1 # provide memory map
.set FLAGS, ALIGN | MEMINFO # this is the Multiboot 'flag' field
.set MAGIC, 0x1BADB002 # 'magic number' lets bootloader find the header
.set CHECKSUM, -(MAGIC + FLAGS) # checksum of above, to prove we are multiboot
.section .multiboot
.align 4
.long MAGIC
.long FLAGS
.long CHECKSUM
.section .bss
.align 16
stack_bottom:
.skip 16384 # 16 KiB
stack_top:
.section .text
.global _start
.type _start, @function
_start:
mov $stack_top, %esp
call kernel_main
cli
1: hlt
jmp 1b
.size _start, . - _start
【问题讨论】:
-
您得到的错误是链接器错误。您没有向我们展示您的
linker.ld,但听起来您正在使用_start的入口点,但您的代码中没有_start标签。 -
_start 在 boot.asm 中定义,这里是 linker.ld pastebin.com/MuJxLQW8
-
你能告诉我们你的
boot.asm。问题是这不是一个最小的完整可验证示例。如果你让你的整个项目可用,那就更好了。 -
我不知道有什么像样的网站可以将其上传到这里ufile.io/5c368 使用 bash 脚本可以正常编译,这就是为什么我认为 makefile 中有错误
-
@flabbyllama 确保
_start是一个全局符号!
标签: gcc assembly makefile linker gnu-assembler