[英]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.