C Sharp Bare Bones

来自osdev
跳到导航 跳到搜索

等等!你是否已阅读过 起步指南, 起步错误, 以及一些相关的 操作系统理论

难度等级
Difficulty 2.png
中等

本教程旨在帮助你在 C# 中编写一个简单的 'Hello World' 操作系统,然后你可以编译为IA32体系结构的机器码并通过GRUB启动。 有许多用于将C# 编译到 CIL 的工具,包括微软的csc (与 Microsoft.NET 一起分发) 和mcs/gmcs/dmcs (与 [mono-project.com Mono] 一起分发)。 此外,还有许多以提前编译方式将 CIL 编译到本机机器码的工具,包括Microsoft的ngen,mono (带有-aot选项),Cosmos的 IL2CPU,来自 [http:// mosa-project.org/projects/mosa MOSA项目]的mosacl 和来自 tysos 项目的tysila。 鉴于作者对tysos的较为程度,我们在这里重点介绍tysos。

先决条件

你将需要一个binutils,它可以从.net,grub及其xorriso依赖 (用于生成iso图像),NASM/YASM/类似的汇编Stub,当然还有tysila,以上这些工具逐步完成针对elf_i386仿真,mono (对于gmcs编译器) 或csc的目标构建。 对于基于debian的系统,请尝试运行sudo apt-get install nasm xorriso qemu mono-devel。

对于tysila,你可以从以下位置下载预编译的二进制文件 http://www.tysos.org/files/tysila/tysila-latest.tar.bz2 (http://web.archive.org/web/20170317154703/http://www.tysos.org/files/tysila/tysila-latest.tar.bz2) 然后在路径下解压它们。 请注意,由于当前Microsoft CLR中的错误,这些二进制文件在64位Windows上不起作用 (请参阅 此处),因此你必须从源代码构建它。

构建tysila

仅当你尚未下载上述预编译的二进制文件时,才需要这样做。 使用subversion获取最新的源代码 “svn co http://www.tysos.org/svn/trunk tysos” (不在Wayback Machine中),或从http://www.tysos.org/files/src/tysos-latest.tar.bz2下载最新的tar包(http://web.archive.org/web/*/http://www.tysos.org/files/src/tysos-latest.tar.bz2)。 Tysos是一个在C# 中开发完整的OS内核和驱动程序的项目,但是我们只想要编译器,因此我们只想编译构建树的一部分。 进入tysos目录并运行

cd tybuild && make && cd ..
cd mono/corlib && make mscorlib.dll && cd ../..
cd tysila2 && make && cd ..

你需要将mono/corlib/mscorlib.dll、tysila2/bin/Release/tysila2.exe、tysila2/bin/Release/libsupcs.dll、tysila2/bin/Release/libtysila.dll、tysila2/bin/Release/tydbfile.dll、tysila2/bin/Release/tydisasm.dll和tybuild/bin/Release/tybuild.exe文件放在路径中的某个地方。

你可能需要为mono启用binfmt_misc支持 (如果在linux上尝试此功能)。 如何做到这一点不在本文档的范围内,但答案很容易通过Google获得。

目录布局

我们将创建一个目录来构建我们的操作系统和ISO文件。 像mkdir -p barebones/iso/boot/grub这样应该足够了。 进入barebones目录,开始创建一些文件。

loader.asm

这是汇编Stub,它要包含一个多引导头。

global sthrow

extern kmain

MODULEALIGN       equ     1<<0
MEMINFO           equ     1<<1
FLAGS             equ     MODULEALIGN | MEMINFO
MAGIC             equ     0x1BADB002
CHECKSUM          equ     -(MAGIC + FLAGS)

section .text

align 4
dd MAGIC
dd FLAGS
dd CHECKSUM

sthrow:
    hlt
    jmp sthrow

kernel.cs

这是实际的简单内核-它只是将消息打印到屏幕上。

namespace BareBones
{
    class Program
    {
        static int pos = 0;

        unsafe static void Main()
        {
            // Clear the screen
            for(int i = 0; i < 80 * 25 * 2; i++)
                *(byte *)(0xb8000 + i) = 0;

            // Say hi
            Print("Hello World!");
        }

        static void Print(string s)
        {
            foreach(char c in s)
                Print(c);
        }

        unsafe static void Print(char c)
        {
            *(byte *)(0xb8000 + pos) = (byte)c;
            *(byte *)(0xb8000 + pos + 1) = 0x0f;
            pos += 2;
        }
    }
}

linker.ld

链接器脚本

ENTRY (_start)

SECTIONS
{
    . = 0x00100000;

    .text ALIGN(0x1000) :
    {
        *(.text)
    }

    .rodata ALIGN(0x1000) :
    {
        *(.rodata*)
    }

    .data ALIGN(0x1000) :
    {
        *(.data)
    }

    .bss ALIGN(0x1000) :
    {
        *(COMMON)
        *(.bss)
    }
}

iso/boot/grub/grub.cfg

这是一个简短的文件,告诉grub在哪里可以找到我们的内核

multiboot /kernel.bin
boot

把它全部构建起来

以下命令应该构建你的新C#内核。首先,组装multiboot stub:

nasm -felf -o loader.o loader.asm

为了编译.cs文件到a.exe你可以选择三个选项 (取决于你的体系结构):

gmcs /target:exe /out:kernel.exe /unsafe kernel.cs
csc /target:exe /out:kernel.exe /unsafe kernel.cs
tybuild.exe /unsafe kernel.cs

要编译kernel.exe到机器码,我们使用tysila:

tysila2.exe --arch i586-elf-tysos -fno-rtti -o kernel.o kernel.exe

在这里,-fno-rtti切换禁用运行时类型信息,如果对其支持将大大扩大内核的大小,并要求你提供大量的运行时功能来支持这一点。

开始链接:

ld -m elf_i386 -T linker.ld -o iso/kernel.bin loader.o kernel.o

然后我们建立一个可启动ISO映像:

grub-mkrescue -o barebones.iso iso

并在qemu上运行它:

qemu-system-i386 -cdrom barebones.iso