自制操作系统Antz day08——实现内核 (中) 扩展内核

简介:   在前几天的任务中,我们已经简单实现了MBR,直接操作显示器和硬盘操作来加载其他扇区的程序,如今已经可以进入保护模式了,并且编写了我们自己的内核程序,这个内核虽然什么也没有做,但还是成功被加载进内存了。接下来我们要将这个内核程序编写详细的内容了。

  Antz系统更新地址: https://www.cnblogs.com/LexMoon/category/1262287.html

  Linux内核源码分析地址: https://www.cnblogs.com/LexMoon/category/1267413.html

  Github地址:https://github.com/CasterWx 

  在前几天的任务中,我们已经简单实现了MBR,直接操作显示器和硬盘操作来加载其他扇区的程序,如今已经可以进入保护模式了,并且编写了我们自己的内核程序,这个内核虽然什么也没有做,但还是成功被加载进内存了。接下来我们要将这个内核程序编写详细的内容了。

0. 切换堆栈和GDT

 1 SELECTOR_KERNEL_CS    equ    8
 2 
 3 extern    cstart
 4 extern    gdt_ptr
 5 
 6 [SECTION .bss]
 7 StackSpace        resb    2 * 1024
 8 StackTop:        
 9 
10 [section .text]    
11 global _start    
12 
13 _start:
14     mov    esp, StackTop
15     sgdt    [gdt_ptr]    
16     call    cstart    
17     lgdt    [gdt_ptr]    
18     jmp    SELECTOR_KERNEL_CS:csinit
19 csinit:        
20     hlt

  这四行代码就可以完成切换堆栈和更换GDT任务了。StackTop定义在.bss段中,大小为2KB,操作GDT时用到了gdt_ptr和cstart分别时一个全局变量和全局函数,定义在c代码start.c中。

#include "type.h"
#include "const.h"
#include "protect.h"

PUBLIC    void*    memcpy(void* pDst, void* pSrc, int iSize);
PUBLIC void    disp_str(char * pszInfo);

PUBLIC    t_8            gdt_ptr[6];     
PUBLIC    DESCRIPTOR        gdt[GDT_SIZE];
 
PUBLIC void cstart()
{
    disp_str("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n-----\"cstart\" begins-----\n");

    memcpy(    &gdt,                    
        (void*)(*((t_32*)(&gdt_ptr[2]))),   
        *((t_16*)(&gdt_ptr[0])) + 1        
        );

    t_16* p_gdt_limit = (t_16*)(&gdt_ptr[0]);
    t_32* p_gdt_base  = (t_32*)(&gdt_ptr[2]);
    *p_gdt_limit = GDT_SIZE * sizeof(DESCRIPTOR) - 1;
    *p_gdt_base  = (t_32)&gdt;
}

 

  cstart()首先把位于Loader中的原GDT全部复制给新的GDT,然后把gdt_ptr中的内容换为新的GDT的基地址和界限。复制GDT用的是memepy,至于它的函数定义就不详细写了,这个是c中非常出名的一个函数了。

  当然还有一些类型,结构体和宏,这些可以放置在.h的头文件中。

  protect.h :

 1 #ifndef    _TINIX_PROTECT_H_
 2 #define    _TINIX_PROTECT_H_
 3 
 4 typedef struct s_descriptor        /* 共 8 个字节 */
 5 {
 6     t_16    limit_low;         
 7     t_16    base_low; 
 8     t_8    base_mid;     
 9     t_8    attr1;         
10     t_8    limit_high_attr2; 
11     t_8    base_high;         
12 }DESCRIPTOR;
13 
14 #endif

  type.h :

 1 #ifndef    _TINIX_TYPE_H_
 2 #define    _TINIX_TYPE_H_
 3 
 4 
 5 typedef    unsigned int        t_32;
 6 typedef    unsigned short        t_16;
 7 typedef    unsigned char        t_8;
 8 typedef    int            t_bool;
 9 
10 
11 #endif 

  const.h :

 1 #ifndef    _TINIX_CONST_H_
 2 #define    _TINIX_CONST_H_
 3 
 4 
 5 #define    PUBLIC     
 6 #define    PRIVATE    static    
 7 
 8 #define    GDT_SIZE    128
 9 
10 
11 #endif

  接下来在linux下编译链接。

  nasm -f elf -o kernel.o kernel.asm

  nasm -f elf -o string.o string.asm

  gcc -c -o start.o start.c

  ld -s  -Ttext 0x30400 -o kernel.bin kernel.o string.o start.o

  将bin使用工具写入(day01或者dd) ,打开查看结果。

  可以看到cstart成功切换了堆栈与GDT。

 

1. Makefile

  随着代码量的增多,编译链接的命令也越来越多了,你可能之前没有接触过Makefile,但这是一个非常高效的东西,值得学习。

  Makefile 是和 make 命令一起配合使用的,很多大型项目的编译都是通过 Makefile 来组织的, 如果没有 Makefile, 那很多项目中各种库和代码之间的依赖关系不知会多复杂,Makefile的组织流程的能力如此之强, 不仅可以用来编译项目, 还可以用来组织我们平时的一些日常操作. 这个需要大家发挥自己的想象力.。

  Makefile基本语法如下:

1 target ... : prerequisites ...
2     command
3     ...
1 target ... : prerequisites ; command
2     command
3     ...

  target也就是一个目标文件,可以是Object File,也可以是执行文件。还可以是一个标签(Label),对于标签这种特性,在后续的“伪目标”章节中会有叙述。

  prerequisites就是要生成那个target所需要的文件或是目标。

 

  command也就是make需要执行的命令。(任意的Shell命令)

 

  这是一个文件的依赖关系,也就是说,target这一个或多个的目标文件依赖于prerequisites中的文件,其生成规则定义在command中。说白一点就是说,prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。这就是Makefile的规则。也就是Makefile中最核心的内容。

 

  来举个例子:

 1 # Makefile for boot
 2 
 3 # Programs, flags, etc.
 4 ASM        = nasm
 5 ASMFLAGS    = 
 6 
 7 # This Program
 8 TARGET        = boot.bin loader.bin
 9 
10 # All Phony Targets
11 .PHONY : everything clean all
12 
13 # Default starting position
14 everything : $(TARGET)
15 
16 clean :
17     rm -f $(TARGET)
18 
19 all : clean everything
20 
21 boot.bin : boot.asm ./include/load.inc ./include/fat12hdr.inc
22     $(ASM) $(ASMFLAGS) -o $@ $<
23 
24 loader.bin : loader.asm ./include/load.inc ./include/fat12hdr.inc ./include/pm.inc
25     $(ASM) $(ASMFLAGS) -o $@ $<

  #是注释的意思, =用来定义变量 , ASM和ASMFLAGS就是两个变量,使用变量要用$(ASM)和$(ASMFLAGS) 。

  对于 target :  prerequistites 

          command 

  意思就是想要得到target就需要指向命令command。

  target依赖于prerequistites,当prerequistites中至少有一个文件比target文件新时,command才会执行。

  看看最后两行,要想得到loader.bin就需要执行命令:$(ASM) $(ASMFLAGS) -o $@ $<

  loader.bin依赖于loader.asm load.inc fat12hdr.inc pm.inc ,这些中只要有一个比target新,command就会执行。

  那么这里的command是什么意思呢?

1 $(ASM) $(ASMFLAGS) -o $@ $<

  $@  $< 其实就是target,prerequistites的第一个名字,所以这个命令等价于

1 nasm -o loader.bin loader.asm

  此外你可能还发现了在外的大标签,他们是动作名称,如everything,all,clean,它们用于make后面,比如make all ,make clean,然后就会执行相应的当作。

  对于Makefile我们目前只需要知道这些就可以了。

  对于Antz内核的编写将会暂时停止几天,最近准备看看Linux内核的相关知识。同步会更新在https://www.cnblogs.com/LexMoon/category/1267413.html

 

目录
相关文章
|
6天前
|
存储 人工智能 安全
操作系统的心脏:内核深度解析
【8月更文挑战第13天】 在数字世界的每一次跳动中,都能感受到操作系统内核的强大生命力。本文将带你走进操作系统的核心——内核,揭示它如何协调和管理计算机硬件资源,保证软件运行的高效和稳定。从内核的定义和功能,到它的结构和设计哲学,再到现代操作系统中的创新与挑战,我们将一起探索这个让计算机系统“活着”的秘密所在。
22 3
|
2月前
|
存储 Cloud Native 物联网
探索操作系统的心脏:内核设计与实现
【6月更文挑战第28天】在数字世界的每一次跳动中,操作系统的内核扮演着不可或缺的角色。本文将深入探讨操作系统内核的设计原理、实现机制以及它们如何影响系统性能和稳定性。我们将从内核的基本概念出发,逐步剖析其核心组件,包括进程管理、内存管理、文件系统和设备驱动等方面。通过分析Linux内核作为案例,揭示现代操作系统内核设计的复杂性和优雅性。文章旨在为读者提供对操作系统内核深层次理解的同时,也展望了未来操作系统可能的发展趋势。
|
9天前
|
存储 安全
操作系统的心脏:内核探秘
【8月更文挑战第10天】 本文带你深入操作系统最神秘的角落,探索内核的奥秘。我们将一窥内核如何协调硬件与软件之间的复杂关系,保持系统稳定运行。通过简明的语言和生动的比喻,你将了解进程管理、内存分配、文件系统等核心概念。无论你是技术新手还是资深爱好者,这篇文章都将为你打开一扇理解计算机深层工作原理的大门。
33 13
|
6天前
|
安全 物联网 云计算
操作系统的心脏:内核探秘
本文将深入剖析操作系统的核心组件——内核,通过浅显易懂的语言和生动的比喻,揭示其神秘面纱。我们将从内核的定义与功能出发,逐步探索进程管理、内存管理等关键模块,并讨论其在现代计算环境中的重要性。无论你是计算机新手还是资深爱好者,这篇文章都将为你打开一扇了解计算机深层工作原理的大门。
10 2
|
14天前
|
存储 网络协议 安全
操作系统的心脏:内核探秘
在数字世界的海洋中,操作系统扮演着船舶的角色,而内核则是推动这艘船前进的引擎。本文将深入探索操作系统内核的设计哲学、功能组件以及它如何影响系统性能和稳定性。我们将通过具体实例来揭示内核对现代计算体验的重要性,并提出一些关于未来操作系统内核发展的思考。
|
6天前
|
算法 调度 UED
操作系统的心脏:内核与进程管理
在数字世界的宏伟建筑中,操作系统是那支撑起一切软件运行的基石。本文将深入浅出地探讨操作系统的核心—内核,以及它如何通过进程管理来协调计算机资源的使用。我们将从内核的定义和功能出发,逐步深入到进程的生命周期,以及调度算法的重要性,最终揭示这些机制如何影响我们日常使用的电子设备性能。
13 2
|
7天前
|
算法 安全 调度
操作系统的心脏:内核深度解析
【8月更文挑战第12天】 本文将带你进入操作系统的核心—内核,探索其设计、功能和工作原理。我们将通过通俗易懂的语言和生动的比喻,让你轻松理解这个复杂但至关重要的主题。无论你是计算机科学的初学者,还是有一定基础的开发者,这篇文章都将为你提供新的视角和深入的理解。让我们一起揭开操作系统内核的神秘面纱,探索它的奥秘吧!
19 3
|
9天前
|
机器学习/深度学习 存储 人工智能
操作系统的心脏:内核探索之旅
【8月更文挑战第11天】在数字世界的宏伟建筑中,操作系统是支撑软件生态和硬件资源协同工作的基石。而在这庞大复杂的系统中,内核则是其跳动的心脏。本文将深入探讨操作系统内核的设计哲学、功能组件以及它在现代计算环境中的作用与挑战。我们将一窥内核如何管理处理器、内存、存储设备等关键资源,并分析它如何在多任务处理、安全性保障及系统性能优化方面扮演至关重要的角色。此外,文章还将讨论当前技术趋势对内核设计的影响,以及未来可能出现的创新方向。
|
9天前
|
安全 Linux Windows
探索操作系统的心脏:内核与用户模式的奥秘
本文将深入探讨操作系统的核心组件——内核,以及它如何通过用户模式和内核模式的切换来管理资源和保护系统安全。我们将从基础概念出发,逐步深入到内核的设计原理,最后讨论现代操作系统中用户模式与内核模式的交互机制。通过这篇文章,读者将获得对操作系统内核工作原理的深刻理解,并认识到它在计算机系统中的重要性。
|
22天前
|
Web App开发 物联网 虚拟化
深入理解操作系统:从内核到用户界面的探索之旅
【7月更文挑战第28天】在数字世界的心脏跳动着的,是复杂而精密的操作系统。它不仅仅是计算机硬件和软件之间的桥梁,更是维系现代计算生态的关键。本文将带领读者穿越操作系统的层层迷雾,从内核的深邃奥秘到用户界面的直观魅力,一探究竟。我们将探讨操作系统如何管理资源、提供接口、确保安全以及适应不断变化的技术需求,揭示这个我们每天都在使用但往往忽视的复杂系统的真实面貌。