文章的范围是什么?

在本文中,我将试图简要介绍文件系统在引导加载程序中的重要性,并尝试编写一个虚拟内核,它只会显示一个提示,让用户输入文本。为什么我要嵌入我的引导加载程序到一个脂肪格式的软盘,它是如何受益于我。因为有一篇文章太小,没有提到文件系统,所以我会尽我最大的努力使它尽可能的简短和简单。

背景

  • 如果您有任何语言的编程经验,这篇文章对您确实有很大帮助。虽然这篇文章似乎相当入门,但在汇编和C中编写程序对于引导来说可能是一项艰巨的任务。如果您是计算机编程新手,那么我建议您阅读一些关于介绍编程和计算机基础的教程,然后再回到本文。
  • 在这篇文章中,我将以问答的方式向您介绍与计算机相关的各种术语。坦率地说,我会写这篇文章,好像我是在向自己介绍这篇文章。为了确保我能理解它在我的日常生活中的重要性和目的,我们已经进行了许多问答式的对话。你所说的计算机是什么意思?或者为什么我需要它们,因为我比它们聪明得多?

此外,您还可以查看我以前的文章,以获得关于引导加载程序的基本概念,以及如何在汇编和C中编写一篇文章。

这是链接。

Http://www.codeproject.com/Articles/664165/Writing-a-boot-loader-in-Assembly-and-C-Part

Http://www.codeproject.com/Articles/668422/Writing-a-boot-loader-in-Assembly-and-C-Part

内容是如何组织的?

这是本文主题的细分部分。

  • 引导加载程序限制
  • 从引导程序调用磁盘上的其他文件
  • FAT文件系统
  • FAT工作流
  • 发展环境
  • 编写一个胖的引导加载程序
  • 发展环境
  • 微型项目-编写一个16位内核
  • 测试内核

引导加载程序限制

在前几篇文章中,我试图编写引导加载程序,在屏幕上打印彩色矩形之后,我想在其中嵌入更多的功能。但是,512字节的大小对我来说是一个很大的限制,我不能更新引导加载程序的代码来做更多的事情.

挑战如下

  • 在引导加载程序中嵌入更多的功能代码
  • 将引导加载程序的大小限制为512字节。

我该如何处理上述问题?

让我向你简要介绍如下。

第一部分:

  • 我将用C语言编写一个名为kernel.c的程序,确保在其中正确地编写了我想要的所有额外功能。
  • 编译可执行文件并将其保存为kernel.bin
  • 现在,将kernel.bin文件复制到可引导驱动器到第二个扇区。

第二部分:

在引导加载程序中,我们所能做的就是将可引导驱动器的第二个扇区(kernel.bin)加载到地址(例如0x1000)的RAM内存中,然后从0x7c00跳转到0x1000位置,开始执行kernel.bin文件。

从引导程序调用磁盘上的其他文件

早些时候,我们了解到,我们实际上可以将控件从引导加载程序(0x7c00)传递到内存中的磁盘文件(如kernel.bin)的其他位置,然后继续进行。但我脑子里没什么疑问。

您知道kernel.bin文件将占用多少扇区吗?

我觉得这很简单。我们所要做的就是
1扇区=512字节
因此,如果kernel.bin的大小是512字节,那么它将占用1个扇区,如果大小为1024字节,则占用2个扇区,以此类推。
现在,重点是基于kernel.bin文件的大小,您必须硬编码引导加载程序中的kernel.bin文件要读取的扇区数。
这意味着,如果您想要通过频繁更新内核来升级内核,您还必须记住记录内核.bin文件在引导加载程序中占据的扇区的数量,否则内核崩溃。

如果您想要在您的可引导驱动器中添加更多的文件,如office.bin、entertainment.bin、drivers.bin、kernel.bin,您会怎么想?

在某个时候,您要做的就是一个一个地将文件附加到软盘中,在这个过程中,您必须继续更新引导加载器,了解引导磁盘上每个文件的确切位置,以及每个文件正在消耗的扇区的数量,以及更多的扇区。

但我想提醒大家的一点是,慢慢地,系统变得越来越复杂,而且不知怎么的,我很喜欢它。

您如何知道您在引导扇区后面附加的文件是否是您想要的文件?

我们所做的就是从引导加载程序将各自的扇区加载到内存中,然后开始执行它。但这并不完美,缺少了一些东西。

少了什么?

我认为引导加载程序对每个文件一个一个地加载扇区,然后开始执行文件。但是即使在引导加载程序尝试将文件加载到内存之前,也应该有一种方法来检查这些文件是否存在于引导磁盘上。

如果我错误地将错误的文件复制到引导磁盘的第二扇区,然后更新引导加载程序,然后运行,会发生什么情况?

我的系统只是崩溃,用户会丢弃我的系统,因为这不是他想要的。

因此,在这种情况下,我所需要的只是引导磁盘上的一个固定位置,其中所有的文件名都像书中的索引一样被写入。

我的引导加载程序将查询软盘的索引,查找文件的名称,如果文件名列在索引中,则继续将文件加载到内存中。

哇!这很好,我喜欢它,因为它节省了很多行动。

这消除了一些问题。

早期的引导加载程序过去盲目地加载其中硬编码的扇区.

如果您不知道正在加载的文件是否正确,为什么要加载该文件?

解决办法是什么?

我们所要做的就是组织上面列出的磁盘上的信息,然后开始组织数据,然后重新编写引导加载程序,这样它才能真正有效地加载文件。

这种大规模组织数据的方法称为文件系统(FileSystem)。有许多类型的文件系统,有商业和免费的。下面我将列举其中的几个。

  • 胖的
  • FAT 16
  • FAT 32
  • NTFS
  • 分机
  • Ext 2
  • EXT 3
  • EXT 4

FAT文件系统

在我向您介绍文件系统之前,您需要了解的术语不多。

在FAT文件系统中,集群占用1个扇区,扇区在存储介质上占512字节。因此,一个集群相当于一个FAT格式化磁盘驱动器上的一个扇区。

集群和扇区是FAT文件系统中最小的单元。

为了便于使用,FAT文件系统分为四个主要部分,它们如下所示。

  • 启动扇区
  • 胖的
  • 根目录
  • 数据区

为了更好的理解,我尽我最大的努力以图片的形式展示给你。

现在让我向你介绍每一部分。

引导扇区:

FAT格式化磁盘上的引导扇区嵌入一些与FAT相关的信息,因此每次将磁盘插入到系统中时,操作系统都会自动知道其文件系统。

操作系统读取FAT格式化磁盘的引导扇区,然后解析所需的信息,然后识别文件系统的类型,然后开始相应地读取内容。

嵌入在引导扇区内的FAT文件系统的信息称为BootParameterBlock。

引导参数块:

让我向您展示引导参数块中有关引导扇区的值。

文件分配表:

此表的作用类似于包含文件的下一个群集值的链接列表。

从FAT中为特定文件获取的群集值有两种有用的方法。

  • 确定文件的结尾

    • 如果集群值在0x0ff8和0x0fff之间,那么该文件在其他扇区中没有数据(到达File的末尾)。
  • 确定文件数据所在的下一个扇区

注:

我在图片中提到了脂肪表1和2。你需要记住的是,一张桌子是另一张桌子的副本。如果来自某个表的数据丢失或损坏,则来自另一个表的数据可以充当备份。这纯粹是为了引入两个表而不是一个表。

根目录:

根目录的作用类似于磁盘上所有文件名列表的索引。因此,引导加载程序应该在根目录中搜索文件名,如果它是正的,那么它可以在根目录中找到第一个集群,然后相应地加载数据。

现在,在从根目录中找到第一个集群之后,引导加载程序应该使用FAT表来查找下一个集群,以检查文件的结尾。

数据区:

这是实际包含文件数据的区域。

一旦程序确定了文件的适当扇区,就可以从数据区域提取文件的数据。

FAT工作流

假设我们的引导加载程序应该将kernel.bin文件加载到内存中,然后执行它。现在,在这个场景中,我们所要做的就是将下面的功能编码到我们的引导加载程序中。

将前11个字节的数据与根目录表中从偏移量0开始的“kernel.bin”进行比较。

如果字符串匹配,则提取根目录表中偏移量26处的“kernel.bin”文件的第一个集群。

现在有了“kernel.bin”文件的启动集群。

您所要做的就是将集群转换为相应的扇区,然后将数据加载到内存中。

现在,在找到“kernel.bin”文件的第一个扇区后,将其加载到内存中,然后在文件的下一个集群的文件分配表中查找,以检查该文件是否仍然具有数据或文件结束。

下面是供您参考的图表。

发展环境

要成功地完成这项任务,我们需要了解以下内容。有关它们的更多信息,请参阅我以前的文章。

  • 操作系统(GNU Linux)
  • 汇编程序(GNU汇编程序)
  • 指令集(x86系列)
  • 在x86微处理器的GNU汇编程序上编写x86指令。
  • 编译器(C编程语言-GNU C编译器GCC)
  • 链接器(GNU链接器ld)
  • 像Bochs这样的x86仿真器用于我们的测试。

编写一个胖的引导加载程序

下面是用于在FAT格式化磁盘上执行kernel.bin文件的代码片段。

下面是引导程序

文件名:stage0.S

/**********************************************************************************                                                                               **                                                                               **    Name       : stage0.S                                                      **    Date       : 23-Feb-2014                                                   **    Version    : 0.0.1                                                         **    Source     : assembly language                                             **    Author     : Ashakiran Bhatter                                             **                                                                               **    Description: The main logic involves scanning for kernel.bin file on a     **                 fat12 formatted floppy disk and then pass the control to it   **                 for its execution                                             **    Usage      : Please read the readme.txt for more information               **                                                                               **                                                                               **********************************************************************************/
.code16
.text
.globl _start;
_start:jmp _bootnop/*bios parameter block                           description of each entity       *//*--------------------                           --------------------------       */.byte 0x6b,0x69,0x72,0x55,0x58,0x30,0x2e,0x31    /* oem label                     */.byte 0x00,0x02                                  /* total bytes per sector        */.byte 0x01                                       /* total sectors per cluster     */.byte 0x01,0x00                                  /* total reserved sectors        */.byte 0x02                                       /* total fat tables              */.byte 0xe0,0x00                                  /* total directory entries       */.byte 0x40,0x0b                                  /* total sectors                 */.byte 0xf0                                       /* media description             */.byte 0x09,0x00                                  /* size in of each fat table     */.byte 0x02,0x01                                  /* total sectors per track       */.byte 0x02,0x00                                  /* total heads per cylinder      */.byte 0x00,0x00, 0x00, 0x00                      /* total hidden sectors          */.byte 0x00,0x00, 0x00, 0x00                      /* total big sectors             */.byte 0x00                                       /* boot drive identifier         */.byte 0x00                                       /* total unused sectors          */.byte 0x29                                       /* external boot signature       */.byte 0x22,0x62,0x79,0x20                        /* serial number                 */.byte 0x41,0x53,0x48,0x41,0x4b,0x49              /* volume label 6 bytes of 11    */.byte 0x52,0x41,0x4e,0x20,0x42                   /* volume label 5 bytes of 11    */.byte 0x48,0x41,0x54,0x54,0x45,0x52,0x22         /* file system type              *//* include macro functions */#include "macros.S"/* begining of main code */
_boot:/* initialize the environment */initEnvironment /* load stage2 */loadFile $fileStage2/* infinite loop */
_freeze:jmp _freeze/* abnormal termination of program */
_abort:writeString $msgAbortjmp _freeze/* include functions */#include "routines.S"/* user-defined variables */bootDrive : .byte 0x0000msgAbort  : .asciz "* * * F A T A L  E R R O R * * *"#fileStage2: .ascii "STAGE2  BIN"fileStage2: .ascii  "KERNEL  BIN"clusterID : .word 0x0000/* traverse 510 bytes from beginning */. = _start + 0x01fe/* append boot signature             */.word BOOT_SIGNATURE

这是主加载程序文件执行以下操作。

  • 初始化所有寄存器并通过调用initEnvironment宏设置堆栈。
  • 调用loadFile宏将kernel.bin文件加载到地址0x1000:0000的内存中,然后将控制传递给它以供进一步执行。

文件名:宏S

这是一个包含所有预定义宏和宏函数的文件。

/*********************************************************************************          *                                                                               **                                                                               **    Name       : macros.S                                                      **    Date       : 23-Feb-2014                                                   **    Version    : 0.0.1                                                         **    Source     : assembly language                                             **    Author     : Ashakiran Bhatter                                             **                                                                               **                                                                               **********************************************************************************/
/* predefined macros: boot loader                         */
#define BOOT_LOADER_CODE_AREA_ADDRESS                 0x7c00
#define BOOT_LOADER_CODE_AREA_ADDRESS_OFFSET          0x0000/* predefined macros: stack segment                       */
#define BOOT_LOADER_STACK_SEGMENT                     0x7c00#define BOOT_LOADER_ROOT_OFFSET                       0x0200
#define BOOT_LOADER_FAT_OFFSET                        0x0200#define BOOT_LOADER_STAGE2_ADDRESS                    0x1000
#define BOOT_LOADER_STAGE2_OFFSET                     0x0000 /* predefined macros: floppy disk layout                  */
#define BOOT_DISK_SECTORS_PER_TRACK                   0x0012
#define BOOT_DISK_HEADS_PER_CYLINDER                  0x0002
#define BOOT_DISK_BYTES_PER_SECTOR                    0x0200
#define BOOT_DISK_SECTORS_PER_CLUSTER                 0x0001/* predefined macros: file system layout                  */
#define FAT12_FAT_POSITION                            0x0001
#define FAT12_FAT_SIZE                                0x0009
#define FAT12_ROOT_POSITION                           0x0013
#define FAT12_ROOT_SIZE                               0x000e
#define FAT12_ROOT_ENTRIES                            0x00e0
#define FAT12_END_OF_FILE                             0x0ff8/* predefined macros: boot loader                         */
#define BOOT_SIGNATURE                                0xaa55/* user-defined macro functions */
/* this macro is used to set the environment */
.macro initEnvironmentcall _initEnvironment
.endm
/* this macro is used to display a string    */
/* onto the screen                           */
/* it calls the function _writeString to     */
/* perform the operation                     */
/* parameter(s): input string                */
.macro writeString messagepushw messagecall  _writeString
.endm
/* this macro is used to read a sector into  */
/* the target memory                         */
/* It calls the _readSector function with    */
/* the following parameters                  */
/* parameter(s): sector Number               */
/*            address to load                */
/*            offset of the address          */
/*            Number of sectors to read      */
.macro readSector sectorno, address, offset, totalsectorspushw sectornopushw addresspushw offsetpushw totalsectorscall  _readSectoraddw  $0x0008, %sp
.endm
/* this macro is used to find a file in the  */
/* FAT formatted drive                       */
/* it calls readSector macro to perform this */
/* activity                                  */
/* parameter(s): root directory position     */
/*               target address              */
/*               target offset               */
/*               root directory size         */
.macro findFile file/* read fat table into memory */readSector $FAT12_ROOT_POSITION, $BOOT_LOADER_CODE_AREA_ADDRESS, $BOOT_LOADER_ROOT_OFFSET, $FAT12_ROOT_SIZEpushw filecall  _findFileaddw  $0x0002, %sp
.endm
/* this macro is used to convert the given   */
/* cluster into a sector number              */
/* it calls _clusterToLinearBlockAddress to  */
/* perform this activity                     */
/* parameter(s): cluster number              */
.macro clusterToLinearBlockAddress clusterpushw clustercall  _clusterToLinearBlockAddressaddw  $0x0002, %sp
.endm
/* this macro is used to load a target file  */
/* into the memory                           */
/* It calls findFile and then loads the data */
/* of the respective file into the memory at */
/* address 0x1000:0x0000                     */
/* parameter(s): target file name            */
.macro loadFile file/* check for file existence */findFile filepushw %ax/* read fat table into memory */readSector $FAT12_FAT_POSITION, $BOOT_LOADER_CODE_AREA_ADDRESS, $BOOT_LOADER_FAT_OFFSET, $FAT12_FAT_SIZEpopw  %axmovw  $BOOT_LOADER_STAGE2_OFFSET, %bx
_loadCluster:pushw %bxpushw %axclusterToLinearBlockAddress %axreadSector %ax, $BOOT_LOADER_STAGE2_ADDRESS, %bx, $BOOT_DISK_SECTORS_PER_CLUSTERpopw  %axxorw %dx, %dxmovw $0x0003, %bxmulw %bxmovw $0x0002, %bxdivw %bxmovw $BOOT_LOADER_FAT_OFFSET, %bxaddw %ax, %bxmovw $BOOT_LOADER_CODE_AREA_ADDRESS, %axmovw %ax, %esmovw %es:(%bx), %axorw  %dx, %dxjz   _even_cluster
_odd_cluster:shrw $0x0004, %axjmp  _done
_even_cluster:and $0x0fff, %ax
_done:popw %bxaddw $BOOT_DISK_BYTES_PER_SECTOR, %bxcmpw $FAT12_END_OF_FILE, %axjl  _loadCluster/* execute kernel */initKernel
.endm
/* parameter(s): target file name            */
/* this macro is used to pass the control of */
/* execution to the loaded file in memory at */
/* address 0x1000:0x0000                     */
/* parameters(s): none                       */
.macro initKernel/* initialize the kernel */movw  $(BOOT_LOADER_STAGE2_ADDRESS), %axmovw  $(BOOT_LOADER_STAGE2_OFFSET) , %bxmovw  %ax, %esmovw  %ax, %dsjmp   $(BOOT_LOADER_STAGE2_ADDRESS), $(BOOT_LOADER_STAGE2_OFFSET)
.endm 

环境:

  • 此宏用于按需要设置段寄存器。
  • 需要传递的参数数为零。

用途:环境

写:

  • 此宏用于将以空结尾的字符串显示到屏幕上。
  • 传递给它的参数是一个以空结尾的字符串变量。

用法:writeString<String变量>

读者群:

  • 此宏用于从磁盘读取给定扇区,然后将其加载到目标地址。
  • 需要传递的参数数为4个。

用途:读取器<扇区编号>、<目标地址>、<目标地址偏移>、<总扇区读取>

FindFile:

  • 此宏用于检查文件是否存在。
  • 传递所需的参数数为1。

用法:findFile<目标文件名>

集群ToLinearBlockAddress:

  • 此宏用于将给定的群集id转换为扇区号。
  • 传递所需的参数数为1。

用法:clusterToLinearBlockAddress<群集ID>

加载文件:

  • 此宏用于将目标文件加载到内存中,然后将执行控件传递给它。
  • 传递所需的参数数为1。

用法:loadFile<目标文件名>

InitKernel:

  • 此宏用于将执行控制传递到RAM上的特定地址位置。
  • 需要传递的参数数为零。

用法:initKernel

文件名:程序化

/**********************************************************************************                                                                               **                                                                               **    Name       : routines.S                                                    **    Date       : 23-Feb-2014                                                   **    Version    : 0.0.1                                                         **    Source     : assembly language                                             **    Author     : Ashakiran Bhatter                                             **                                                                               **                                                                               **********************************************************************************/
/* user-defined routines */
/* this function is used to set-up the */
/* registers and stack as required     */
/* parameter(s): none                  */
_initEnvironment:pushw %bpmovw  %sp, %bp
_initEnvironmentIn:climovw  %cs, %axmovw  %ax, %dsmovw  %ax, %esmovw  %ax, %ssmovw  $BOOT_LOADER_STACK_SEGMENT, %spsti
_initEnvironmentOut:movw  %bp, %sppopw  %bp
ret/* this function is used to display a string */
/* onto the screen                           */
/* parameter(s): input string                */
_writeString:pushw %bpmovw  %sp   , %bpmovw 4(%bp) , %sijmp  _writeStringCheckByte
_writeStringIn:movb $0x000e, %ahmovb $0x0000, %bhint  $0x0010incw %si
_writeStringCheckByte:movb (%si)  , %alorb  %al    , %aljnz  _writeStringIn
_writeStringOut:movw %bp    , %sppopw %bp
ret/* this function is used to read a sector    */
/* into the target memory                    */
/* parameter(s): sector Number               */
/*            address to load                */
/*            offset of the address          */
/*            Number of sectors to read      */
_readSector:pushw %bpmovw %sp    , %bpmovw 10(%bp), %axmovw $BOOT_DISK_SECTORS_PER_TRACK, %bxxorw %dx    , %dxdivw %bxincw %dxmovb %dl    , %clmovw $BOOT_DISK_HEADS_PER_CYLINDER, %bxxorw %dx    , %dxdivw %bxmovb %al    , %chxchg %dl    , %dhmovb $0x02  , %ahmovb 4(%bp) , %almovb bootDrive, %dlmovw 8(%bp) , %bxmovw %bx    , %esmovw 6(%bp) , %bxint  $0x13jc   _abortcmpb 4(%bp) , %aljc   _abortmovw %bp    , %sppopw %bp
ret/* this function is used to find a file in   */
/* the FAT formatted drive                   */
/* parameter(s): root directory position     */
/*               target address              */
/*               target offset               */
/*               root directory size         */
_findFile:pushw %bpmovw  %sp   , %bpmovw  $BOOT_LOADER_CODE_AREA_ADDRESS, %axmovw  %ax   , %esmovw  $BOOT_LOADER_ROOT_OFFSET, %bxmovw  $FAT12_ROOT_ENTRIES, %dxjmp   _findFileInitValues_findFileIn:movw  $0x000b  , %cxmovw  4(%bp)   , %sileaw  (%bx)    , %direpe  cmpsbje    _findFileOut
_findFileDecrementCount:decw  %dxaddw  $0x0020, %bx
_findFileInitValues:cmpw  $0x0000, %dxjne   _findFileInje    _abort
_findFileOut:addw  $0x001a  , %bxmovw  %es:(%bx), %axmovw  %bp, %sppopw  %bp
ret/* this function is used to convert the given*/
/* cluster into a sector number              */
/* parameter(s): cluster number              */
_clusterToLinearBlockAddress:pushw %bpmovw  %sp    , %bpmovw  4(%bp) , %ax
_clusterToLinearBlockAddressIn:subw  $0x0002, %axmovw  $BOOT_DISK_SECTORS_PER_CLUSTER, %cxmulw  %cxaddw  $FAT12_ROOT_POSITION, %axaddw  $FAT12_ROOT_SIZE, %ax
_clusterToLinearBlockAddressOut:movw  %bp    , %sppopw  %bp
ret

_环境:

  • 此函数用于按需要设置段寄存器。
  • 需要传递的参数数为零。

用法:Call_initEnvironment
_写:

  • 此函数用于将以空结尾的字符串显示到屏幕上。
  • 传递给它的参数是一个以空结尾的字符串变量。

用法:

  • 推<字符串变量>
  • 调用写字符串
  • 加$0x02,%sp

读者群:

  • 此宏用于从磁盘读取给定扇区,然后将其加载到目标地址。
  • 需要传递的参数数为4个。

用法:

  • 推<扇形>
  • 推<地址>
  • 推送<偏移>
  • 推动<总扇区>
  • 呼叫读取器
  • 加$0x0008,%sp

FindFile:

  • 此函数用于检查文件是否存在。
  • 传递所需的参数数为1。

用法:

  • 推送<目标文件变量>
  • 调用查找文件
  • 加$0x02,%sp

集群ToLinearBlockAddress:

  • 此宏用于将给定的群集id转换为扇区号。
  • 传递所需的参数数为1。

用法:

  • 推<群集ID>
  • 调用集群ToLinearBlockAddress
  • 加$0x02,%sp

加载文件:

  • 此宏用于将目标文件加载到内存中,然后将执行控件传递给它。
  • 传递所需的参数数为1。

用法:

  • 推送<目标文件>
  • 调用加载文件
  • 加$0x02,%sp

文件名:stage0.ld
此文件用于在链接时间内链接stage0.object文件。

/**********************************************************************************                                                                               **                                                                               **    Name       : stage0.ld                                                     **    Date       : 23-Feb-2014                                                   **    Version    : 0.0.1                                                         **    Source     : assembly language                                             **    Author     : Ashakiran Bhatter                                             **                                                                               **                                                                               **********************************************************************************/
SECTIONS
{. = 0x7c00;.text :{_ftext = .;} = 0
}

文件名:bochsrc.txt

这是运行Bochs模拟器所需的配置文件,用于测试目的。

megs: 32
floppya: 1_44=../iso/stage0.img, status=inserted
boot: a
log: ../log/bochsout.txt
mouse: enabled=0

微型项目-编写一个16位内核

下面的文件是作为测试过程的一部分引入的虚拟内核的源代码。我们所要做的就是使用make文件编译源代码,并查看它是否由引导程序加载。
在文本中显示带有龙图像的飞溅屏幕,然后显示欢迎屏幕和命令提示符,以便用户键入任何内容。
这里没有写好要执行的命令或实用程序,但只是为了测试目的,引入了这个内核,到目前为止,它还是一文不值的。

文件名:kernel.c/********************************************************************************* * * * * * Name : kernel.c * * Date : 23-Feb-2014 * * Version : 0.0.1 * * Source : C * * Author : Ashakiran Bhatter * * * * Description: This is the file that the stage0.bin loads and passes the * * control of execution to it. The main functionality of this * * program is to display a very simple splash screen and a * * command prompt so that the user can type commands * * Caution : It does not recognize any commands as they are not programmed * * * *********************************************************************************/ /* generate 16 bit code */ __asm__(".code16n"); /* jump to main function or program code */ __asm__("jmpl $0x1000, $mainn"); #define TRUE 0x01 #define FALSE 0x00 char str[] = "$> "; /* this function is used to set-up the */ /* registers and stack as required */ /* parameter(s): none */ void initEnvironment() { __asm__ __volatile__( "cli;" "movw $0x0000, %ax;" "movw %ax, %ss;" "movw $0xffff, %sp;" "cld;" ); __asm__ __volatile__( "movw $0x1000, %ax;" "movw %ax, %ds;" "movw %ax, %es;" "movw %ax, %fs;" "movw %ax, %gs;" ); } /* vga functions */ /* this function is used to set the */ /* the VGA mode to 80*24 */ void setResolution() { __asm__ __volatile__( "int $0x10" : : "a"(0x0003) ); } /* this function is used to clear the */ /* screen buffer by splitting spaces */ void clearScreen() { __asm__ __volatile__ ( "int $0x10" : : "a"(0x0200), "b"(0x0000), "d"(0x0000) ); __asm__ __volatile__ ( "int $0x10" : : "a"(0x0920), "b"(0x0007), "c"(0x2000) ); } /* this function is used to set the */ /* cursor position at a given column */ /* and row */ void setCursor(short col, short row) { __asm__ __volatile__ ( "int $0x10" : : "a"(0x0200), "d"((row <<= 8) | col) ); } /* this function is used enable and */ /* disable the cursor */ void showCursor(short choice) { if(choice == FALSE) { __asm__ __volatile__( "int $0x10" : : "a"(0x0100), "c"(0x3200) ); } else { __asm__ __volatile__( "int $0x10" : : "a"(0x0100), "c"(0x0007) ); } } /* this function is used to initialize*/ /* the VGA to 80 * 25 mode and then */ /* clear the screen and set the cursor*/ /* position to (0,0) */ void initVGA() { setResolution(); clearScreen(); setCursor(0, 0); } /* io functions */ /* this function is used to get a chara*/ /* cter from keyboard with no echo */ void getch() { __asm__ __volatile__ ( "xorw %ax, %axn" "int $0x16n" ); } /* this function is same as getch() */ /* but it returns the scan code and */ /* ascii value of the key hit on the */ /* keyboard */ short getchar() { short word; __asm__ __volatile__( "int $0x16" : : "a"(0x1000) ); __asm__ __volatile__( "movw %%ax, %0" : "=r"(word) ); return word; } /* this function is used to display the*/ /* key on the screen */ void putchar(short ch) { __asm__ __volatile__( "int $0x10" : : "a"(0x0e00 | (char)ch) ); } /* this function is used to print the */ /* null terminated string on the screen*/ void printString(const char* pStr) { while(*pStr) { __asm__ __volatile__ ( "int $0x10" : : "a"(0x0e00 | *pStr), "b"(0x0002) ); ++pStr; } } /* this function is used to sleep for */ /* a given number of seconds */ void delay(int seconds) { __asm__ __volatile__( "int $0x15" : : "a"(0x8600), "c"(0x000f * seconds), "d"(0x4240 * seconds) ); } /* string functions */ /* this function isused to calculate */ /* length of the string and then return*/ /* it */ int strlength(const char* pStr) { int i = 0; while(*pStr) { ++i; } return i; } /* UI functions */ /* this function is used to display the */ /* logo */ void splashScreen(const char* pStr) { showCursor(FALSE); clearScreen(); setCursor(0, 9); printString(pStr); delay(10); } /* shell */ /* this function is used to display a */ /* dummy command prompt onto the screen */ /* and it automatically scrolls down if */ /* the user hits return key */ void shell() { clearScreen(); showCursor(TRUE); while(TRUE) { printString(str); short byte; while((byte = getchar())) { if((byte >> 8) == 0x1c) { putchar(10); putchar(13); break; } else { putchar(byte); } } } } /* this is the main entry for the kernel*/ void main() { const char msgPicture[] = " .. nr" " ++` nr" " :ho. `.-/++/. nr" " `/hh+. ``:sds: nr" " `-odds/-` .MNd/` nr" " `.+ydmdyo/:--/yMMMMd/ nr" " `:+hMMMNNNMMMddNMMh:` nr" " `-:/+++/:-:ohmNMMMMMMMMMMMm+-+mMNd` nr" " `-+oo+osdMMMNMMMMMMMMMMMMMMMMMMNmNMMM/` nr" " ``` .+mMMMMMMMMMMMMMMMMMMMMMMMMMMMMNmho:.` nr" " `omMMMMMMMMMMMMMMMMMMNMdydMMdNMMMMMMMMdo+- nr" " .:oymMMMMMMMMMMMMMNdo/hMMd+ds-:h/-yMdydMNdNdNN+ nr" " -oosdMMMMMMMMMMMMMMd:` `yMM+.+h+.- /y `/m.:mmmN nr" " -:` dMMMMMMMMMMMMMd. `mMNo..+y/` . . -/.s nr" " ` -MMMMMMMMMMMMMM- -mMMmo-./s/.` ` nr" " `+MMMMMMMMMMMMMM- .smMy:.``-+oo+//:-.` nr" " .yNMMMMMMMMMMMMMMd. .+dmh+:. `-::/+:. nr" " y+-mMMMMMMMMMMMMMMm/` ./o+-` . nr" " :- :MMMMMMMMMMMMMMMMmy/.` nr" " ` `hMMMMMMMMMMMMMMMMMMNds/.` nr" " sNhNMMMMMMMMMMMMMMMMMMMMNh+. nr" " -d. :mMMMMMMMMMMMMMMMMMMMMMMNh:` nr" " /. .hMMMMMMMMMMMMMMMMMMMMMMMMh. nr" " . `sMMMMMMMMMMMMMMMMMMMMMMMMN. nr" " hMMMMMMMMMMMMMMMMMMMMMMMMy nr" " +MMMMMMMMMMMMMMMMMMMMMMMMh "; const char msgWelcome[] = " *******************************************************nr" " * *nr" " * Welcome to kirUX Operating System *nr" " * *nr" " *******************************************************nr" " * *nr" " * *nr" " * Author : Ashakiran Bhatter *nr" " * Version: 0.0.1 *nr" " * Date : 01-Mar-2014 *nr" " * *nr" " ******************************************************"; initEnvironment(); initVGA(); splashScreen(msgPicture); splashScreen(msgWelcome); shell(); while(1); }

让我简单介绍一下这些职能:

环境():

  • 这是一个函数,用于设置段寄存器,然后设置堆栈.
  • 所需参数为零。
  • 用途:initEnvironment();

SET决议():

  • 此函数用于将视频模式设置为80*25。
  • 所需参数为零。
  • 用法:set决议();

ClearScreen():

  • 此函数用于用空格填充屏幕缓冲区。
  • 所需参数数为零。
  • 用途:ClearScreen();

SetCursor():

  • 此函数用于设置屏幕上给定位置的光标位置。
  • 所需参数数为2。
  • 用法:setCursor(列、行);

秀柯莎():

  • 此函数用于根据用户的选择启用或禁用游标。
  • 所需参数数为1。
  • 用法:显示电流(1);

InitVGA():

  • 此函数用于将视频分辨率设置为80*25,然后清除屏幕,最后将光标设置为(0,0)在屏幕上。
  • 所需参数数为零。
  • 用法:initVGA();

Getch():

  • 此函数用于从没有回显的用户处获得击键。
  • 所需参数数为零。
  • 用法:Getch();

Getchar():

  • 此函数用于返回键扫描代码和相应的ascii代码。
  • 所需参数为零。
  • 用法:putchar();

Putchar():

  • 此函数用于在屏幕上显示字符。
  • 所需参数数为1。
  • 用法:putchar(字符);

PrintString():

  • 此函数用于返回键扫描代码和相应的ascii代码。
  • 所需参数为零。
  • 用法:getchar();

延迟():

  • 此函数用于显示以空结尾的字符串。
  • 所需参数数为1。
  • 用法:printString(空终止字符串变量);

链长():

  • 此函数用于返回以空结尾的字符串的长度。
  • 所需参数数为1。
  • 用法:字符串长度(空终止字符串变量);

SplashScreen():

  • 这个函数被用来在屏幕上显示一些花哨的图像一段时间。
  • 所需参数数为1。
  • 用法:SplashScreen(空终止字符串变量);

外壳():

  • 此函数用于在屏幕上显示提示符。
  • 所需参数为零。
  • 用法:shell();

下面是引导加载程序加载的内核的屏幕截图。

测试内核

使用“源代码”:

附加的是文件源ecode.tar.gz,它包含所需的源文件以及生成二进制文件所需的目录。

因此,请确保您是系统的超级用户,然后开始将文件解压缩到目录或文件夹中。

请确保安装了Bochs-x64模拟器和GNU bin-utils,以便进一步编译和测试源代码。

下面是从zip中提取文件后将看到的目录结构。

应该有5个目录

  • 箱子
  • 国际标准化组织
  • 原木
  • SRC

一旦环境就绪,请确保打开一个终端,然后运行以下命令

  • CD$(目录)/src
  • Mak-f制造试验
  • 博克斯

图表控件 c++_用C/C++编写16位虚拟内核相关推荐

  1. java绘制图表控件_画图控件 Chart Control -Java架构师必看

    .NET3.5中中推出了图表控件,可以同时支持Web和WinForm两种方式,由于平时很少使用,一直网络 .NET3.5中中推出了图表控件,可以同时支持Web和WinForm两种方式,由于平时很少使用 ...

  2. 道路测量xy坐标表示什么_.NET图表控件LightningChart.NET案例研究:智能测量解决方案...

    LightningChart.NET原名LightningChart Ultimate SDK. LightningChart.NET完全由GPU加速,并且性能经过优化,可用于实时显示海量数据-超过1 ...

  3. delphi 图表 控件_将基本图表集成到Delphi应用程序中

    delphi 图表 控件 In most modern database applications some kind of graphical data representation is pref ...

  4. 构建仪表、图表控件的绘制框架

    开发环境: VS2003 + Windows XP SP2测试环境: Windows XP SP2Demo截图 编写图形相关的控件需要完成两部分:1 绘制:2 与窗口类(泛指)集成使之成为控件.本文重 ...

  5. 微软图表控件MsChart

    转自:http://tech.ddvip.com/2008-11/122640479791375.html 昨天在网上看到了微软发布了.NET 3.5框架下的图表控件,第一时间抓下来看了一下,发觉功能 ...

  6. 跨平台图表控件TeeChart使用教程:导入XML数据

    2019独角兽企业重金招聘Python工程师标准>>> TeeChart的最新版中包含了一个自动加载XML数据的新组件.这个组件的名字叫做TTeeXMLSource,用户可以在Tee ...

  7. 漂亮好用的ASP.NET图表控件 免费的

    绝对免费,绝对好用,中文支持绝对好,轻松生成漂亮的2D和3D图表. 这个控件是我找到的免费图表控件中非常好的一个,我一直在关注这个控件,虽然功能未必比得上商业的图表控件强大,但是绝对好用,绝对免费,他 ...

  8. labview波形图两个游标,LabVIEW数据可视化:使用波形图表控件逐点显示曲线的方法...

    LabVIEW平台中提供了强大的2D/3D数据的可视化控件,如波形图.波形图表.XY图.强度图.数字波形图.混合信号图.二维/三维图片及用于特殊用途的极坐标图.Smith图.雷达图控件等. 上篇文章: ...

  9. 微软图表控件MsChart使用说明[转]

    微软图表控件MsChart使用说明 建立一个.NET3.5的Web项目,像使用普通控件一样拖放到要使用的Web界面即可.初步研究了一下,整个图形控件主要由以下几个部份组成: 1.Annotations ...

最新文章

  1. mysql40190_MySQL 内核深度优化
  2. GNU ARM汇编--(二)汇编编译链接与运行
  3. 抽象类和接口有什么区别?
  4. 计算机动漫设计VR主要学什么,动漫设计专业学什么 要学什么软件
  5. 百度API_获取当前详细地址
  6. 一些奇妙的线段树操作
  7. https://zeplin.io/ 设计图标注及切图
  8. LeetCode(884)——两句话中的不常见单词(JavaScript)
  9. 买基金的一个很重要的知识
  10. disruptor小结--生产者代码
  11. 蜘蛛侠天堂,打死我mac键盘
  12. 485转61850规约转换C语言,61850规约转换器
  13. 目标检测之FPN网络详解
  14. 计算机如何输入极限符号,如何录入文本与符号 输入极限公式:Word符号与公式录入宝典第八篇...
  15. python求方程的根_python计算方程式根的方法
  16. Excel中如果对合并单元格求和
  17. 机器学习算法基础之使用python代码
  18. 茗香茶艺网/茶叶宣传网站
  19. Linux下Nginx+Resin负载均衡,session问题解决实例
  20. 【开发工具】SVN断网续传、续下解决办法

热门文章

  1. 多个硬件体验如一,华为终端分布式技术会重构IoT生态吗?
  2. 乐橙本地录像回放不了_本地工具访问:安全、高效、合规的IT资源远程访问
  3. 服务器手工修改虚拟内存,服务器修改虚拟内存
  4. mysql 嵌入式 c开发环境_【Linux】嵌入式C语言MySQL编程(libmysqlclient-dev使用)
  5. vue抽屉_VUE组件中的 Drawer 抽屉实现代码
  6. Java爬虫技术(一)普通网站爬取图片
  7. 解决w: pt/sources.list:18 中被配置了多次
  8. idea没有out文件夹_史上最详细没有之一的 Java JNI傻瓜级入门教程
  9. 结构体命名中的尾标ST是什么意思?(struct)
  10. int main中char** argv与char *argv[]区别?(main函数)