[英]Weird linker error gcc when following simple kernel tutorial
我正在关注如何制作一个简单的可引导内核的教程:http ://www.osdever.net/tutorials/view/writing-a-simple-c-kernel
教程中有以下必需文件:
kernel.c 源代码:
#define WHITE_TXT 0x07 // white on black text
void k_clear_screen();
unsigned int k_printf(char *message, unsigned int line);
k_main() // like main in a normal C program
{
k_clear_screen();
k_printf("Hi!\nHow's this for a starter OS?", 0);
};
void k_clear_screen() // clear the entire text screen
{
char *vidmem = (char *) 0xb8000;
unsigned int i=0;
while(i < (80*25*2))
{
vidmem[i]=' ';
i++;
vidmem[i]=WHITE_TXT;
i++;
};
};
unsigned int k_printf(char *message, unsigned int line) // the message and then the line #
{
char *vidmem = (char *) 0xb8000;
unsigned int i=0;
i=(line*80*2);
while(*message!=0)
{
if(*message=='\n') // check for a new line
{
line++;
i=(line*80*2);
*message++;
} else {
vidmem[i]=*message;
*message++;
i++;
vidmem[i]=WHITE_TXT;
i++;
};
};
return(1);
};
kernel_start.asm 源代码:
[BITS 32]
[global start]
[extern _k_main] ; this is in the c file
start:
call _k_main
cli ; stop interrupts
hlt ; halt the CPU
link.ld 源代码:
OUTPUT_FORMAT("binary")
ENTRY(start)
SECTIONS
{
.text 0x100000 : {
code = .; _code = .; __code = .;
*(.text)
. = ALIGN(4096);
}
.data : {
data = .; _data = .; __data = .;
*(.data)
. = ALIGN(4096);
}
.bss :
{
bss = .; _bss = .; __bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .; _end = .; __end = .;
}
编译它的指令是:
nasm -f aout kernel_start.asm -o ks.o
gcc -c kernel.c -o kernel.o
ld -T link.ld -o kernel.bin ks.o kernel.o
我能够成功执行前两行:
nasm -f aout kernel_start.asm -o ks.o
gcc -c kernel.c -o kernel.o
然后当我尝试运行此行时:
ld -T link.ld -o kernel.bin ks.o kernel.o
我收到错误:
C:\basic_kernel>ld -T link.ld -o kernel.bin ks.o kernel.o
ks.o: file not recognized: File format not recognized
有谁知道这是为什么以及我如何解决这个问题? 我正在使用 Windows 7 64 位
您需要将-f aout
更改为-f elf
以链接生成的目标文件。
现代链接器将期待 ELF 和/或 Windows PECOFF; 您的显然无法识别过时的 a.out 目标文件格式。
当没有使用-f
选项给出格式时,NASM 默认为平面二进制模式,因此完全删除它不是你想要的。
您的gcc
和ld
可能需要 PECOFF 或 ELF 对象文件,而不是旧的和过时的 a.out。 尝试更换-f aout
从nasm
调用与-f elf
一个ELF32 .o
或-f win32
一个PECOFF .obj
(完全删除-f
为您提供默认的-f bin
flat 二进制文件,例如.com
可执行文件或 MBR 引导扇区,而不是链接器输入。)
如果这不起作用,请尝试将此文件命名为ks.s
,使用gcc ks.s -c -o ks.o
组装它,并使用它代替您拥有的ks.o
/ kernel_start.asm
:
.text
.code32
.globl start
start:
call _k_main
cli
hlt
警告:它没有出现在这个例子中,但是当你以这种方式编写汇编时使用的指令语法与你可能期望的非常不同。 这个 SO 问题链接到指南。 使用 GAS 的.intel_syntax noprefix
指令将为您提供与 NASM 不同的语法; 它更像是 MASM。
要注意的其他问题:在程序_k_main
的符号_k_main
的开头不应该有下划线的_k_main
。 在 C 中定义的所有符号开头的下划线是它在 a.out 中的工作方式,但在 ELF 中没有。 我不知道 PECOFF。
我不使用 Windows,所以我不知道这如何适用于您的问题,但是我在编译内核时曾经遇到过同样的问题(ld 给了我相同的错误代码)。 问题是我的代码是由 clang 编译的,而不是由我的工具链的 GCC 编译的,因此当我的工具链的 ld 尝试链接它时,它无法读取目标文件,因为它们不是它所期望的格式. 如果您没有使用 x86 工具链(交叉编译器),请使用一个并确保您使用该工具链中包含的 GCC 来编译您的文件。
将 kernel.asm 中的 _k_main 替换为 k_main,如下所示:
[BITS 32]
[global start]
[extern k_main] ; include the c kernel
start:
call k_main ; call the c kernel
cli ; stop interrupts
hlt ; halt the CPU
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.