【发布时间】:2012-03-22 07:24:29
【问题描述】:
我正在用 C 和 ASM 编写一个简单的内核(调用由 C 编译生成的汇编指令)。我正在关注 osdev.org 上的这篇优秀文章。在阅读了用汇编编写的内核并编译并执行后,它运行良好,我看到 kernel.bin 在 qemu 上运行,太棒了。但我真的很想用 C 来写。我在同一个网页上找到了an example。
我编译了它并尝试在 qemu 上运行 kernel.bin,但我从所有设备上得到“启动失败”:硬盘、floopd 和 CD-rom。然后我将 ks.o(使用 nasm 组装的 kernel.asm)和 kernel.o(使用 gcc 组装的 kernel.c)生成的 kernel.bin 反汇编为使用 ld 组装的 bin 文件。 kernel.bin:
http://pastebin.com/Y0pLFvij我看不到我的字符串或任何汇编指令将我的字符串写在视频上。
生成它的 C 代码:
#define WHITE_TXT 0x07 // white on black text
unsigned int k_printf(char *message, unsigned int line);
void k_clear_screen();
k_main()
{
k_clear_screen();
k_printf("Hi!\nHow's this for a starter OS?", 0);
};
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);
};
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++;
};
以及调用它的assembly:
[bits 32]
[global start]
[extern k_main] ; this is in the c file
start:
call k_main
cli ; stop interrupts
hlt ; halt the CPU
链接.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 = .;
}
和生成文件:
bin:
nasm -f aout -o ks.o kernelbase.asm
gcc -Wall -c -o kernel.o kernel.c
ld -T link.ld -o kernel.bin ks.o kernel.o
run1:
qemu kernel.bin
clear:
rm -f *.o
cbin:
rm -f *.bin
和内核在纯汇编中,反汇编:http://pastebin.com/Bkvkq3YQ 这对我来说效果很好,我可以看到在视频上写字的说明。
我的操作系统:Ubuntu 10.4
编译器:gcc
汇编器:NASM
我哪里错了?
【问题讨论】:
-
缺少代码。 C 代码不可能以这种形式编译。
-
不,C 代码编译得不太好。此外,还有警告。
-
您认为 C 转换为 asm 然后组装和“真正用 C 编写”之间的区别是什么。当然 gcc 会这样做,你编译一个 c 程序,它编译成 asm,然后为你调用汇编器和链接器。没有区别(只要您使用相同的编译器/汇编器/链接器、编译选项和链接器脚本。
-
@NiklasB.:如何删除此警告?
-
@dwelch:我知道没有区别,都是组装。当我说“用 C 编写”时,是使用 C 语法和 C 编译器进行汇编。