我遵循本教程,介绍如何制作一个简单的可启动内核: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位
答案 0 :(得分:4)
您需要将-f aout
更改为-f elf
才能链接生成的目标文件。
现代链接器将期待ELF和/或Windows PECOFF;你明显无法识别过时的a.out对象文件格式。
如果没有使用-f
选项的格式,NASM默认为平面二进制模式,因此完全删除它不是您想要的。
答案 1 :(得分:1)
您的gcc
和ld
可能需要PECOFF或ELF目标文件,而不是旧的和过时的a.out。尝试将-f aout
调用nasm
替换为-f elf
,以获取ELF32 .o
或-f win32
替换PECOFF .obj
(完全删除-f
会为您提供默认的-f bin
平面二进制文件,例如.com
可执行文件或MBR引导程序,而不是链接器输入。)
如果这不起作用,请尝试命名此文件ks.s
,将其与gcc ks.s -c -o ks.o
汇总,并使用代替 ks.o
/ {{ 1}}你有:
kernel_start.asm
警告:在此示例中没有显示,但是以这种方式编写汇编时使用的指令语法与您可能期望的非常不同。 This SO question指向指南。使用GAS的 .text
.code32
.globl start
start:
call _k_main
cli
hlt
指令将提供与NASM不同的语法;它更像是MASM。
要注意的额外皱纹:在装配中符号.intel_syntax noprefix
的开头,不的下划线有很好的几率。在C中定义的所有符号的开头的下划线是它在a.out中的工作方式,但不是在ELF中完成的。我不知道PECOFF。
答案 2 :(得分:0)
我不使用Windows,所以我不知道这将如何适用于你的问题,但我曾经在编译我的内核时遇到了同样的问题(ld给了我相同的错误代码)。问题是我的代码是由clang编译而不是由我的工具链的GCC编译的,因此当我的工具链的ld试图链接它时,它无法读取目标文件,因为它们不是它期望的格式。如果您没有使用x86工具链(交叉编译器),请使用一个工具链,并确保使用该工具链中包含的GCC来编译文件。
答案 3 :(得分:0)
在kernel.asm中用k_main替换_k_main,如下所示:
[BITS 32] ; inform the processor of 32 bits mode program
[global start]
[extern k_main] ; include the c kernel
start:
call k_main ; call the c kernel
cli ; stop interrupts
hlt ; halt the CPU