自制操作系统Antz day07——实现内核 (上)

简介: 在前几天的任务中,我们已经简单实现了MBR,直接操作显示器和硬盘操作来加载其他扇区的程序,如今已经可以进入保护模式了,简单引入了C语言,接下来我们编写自己的内核。

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

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

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

  在前几天的任务中,我们已经简单实现了MBR,直接操作显示器和硬盘操作来加载其他扇区的程序,如今已经可以进入保护模式了,简单引入了C语言,接下来我们编写自己的内核。

0. 汇编生成ELF

  完成实模式到保护模式跳转的这一任务是由loader进行的,而我们不应该用loader做太多的事,loader只需要完成跳转就好了,剩下的工作交给内核。

  为了加载内核到内存,需要使用ELF格式,如何编译这种格式呢?

  来看看下面这个例子。

[section .data]

strHello    db    "Hello, Antz !", 0Ah
STRLEN        equ    $ - strHello


[section .text]    

global _start    

_start:
    mov    edx, STRLEN
    mov    ecx, strHello
    mov    ebx, 1
    mov    eax, 4        
    int    0x80        
    mov    ebx, 0
    mov    eax, 1
    int    0x80    

  global _start定义了程序的入口地址,相当于c/c++中main。

  接下来使用NASM编译。

  

  -f elf 指定了输出文件的格式为ELF格式。

  编译完成之后要进行链接,链接指令如下:

  

    (出现警告,在linux无警告,Windows下会有,可以无视)

  -s是strip的简写,可以去掉符号表等内容,对生成的可执行代码进行减肥。

 

1. 汇编与C语言共同使用

  我们已经可以生成一个支持载入内存的内核格式文件了,现在我们要学会把汇编程序和c语言程序链接在一起。这是我们编写内核的一大步。

  先来看看c代码:

    其中定义了一个choose函数,声明了一个myprint函数。

 1 void myprint(char* msg, int len);
 2 
 3 int choose(int a, int b)
 4 {
 5     if(a >= b){
 6         myprint("the 1st one\n", 13);
 7     }
 8     else{
 9         myprint("the 2nd one\n", 13);
10     }
11 
12     return 0;
13 }

 

  再来看看汇编代码:

 1 extern choose
 2 
 3 
 4 [section .data]    ; 数据在此
 5 
 6 num1st        dd    3
 7 num2nd        dd    4
 8 
 9 
10 [section .text]    ; 代码在此
11 
12 global _start    
13 global myprint    
14 
15 _start:
16     push    num2nd        
17     push    num1st        
18     call    choose        
19     add    esp, 4        
20 
21     mov    ebx, 0
22     mov    eax, 1        
23     int    0x80    
24 
25 ; void myprint(char* msg, int len)
26 myprint:
27     mov    edx, [esp + 8]    ; len
28     mov    ecx, [esp + 4]    ; msg
29     mov    ebx, 1
30     mov    eax, 4        ; sys_write
31     int    0x80    
32     ret
33     

  如果你懂汇编,这个代码一定没有如何问题。

  第一行的extern choose就是指c代码中定义的choose函数。

  后面的global导出了函数入口,_start和在c文件中没有定义的myprint函数,myprint在汇编代码中完成了定义。

  _start中调用了choose,choose中又调用了myprint函数。

  这样这两个代码文件内容就很清晰了吧。

  在Linux终端下查看结果:

1 nasm -f elf foo.asm -o foo.o
2 gcc -c bar.c -o bar.o
3 ld -s hello.o bar.o -o foobar
4 ./foobar

2. 从Loader到内核

  加载内核到内存和引导扇区的工作很相似,只是处理内核时我们要根据ELF文件结构中的值将内核中相应段放入相应位置。

  fat12hdr.inc :

 1 BS_OEMName    DB 'Antz__Os'
 2 
 3 BPB_BytsPerSec    DW 512    
 4 BPB_SecPerClus    DB 1        
 5 BPB_RsvdSecCnt    DW 1
 6 BPB_NumFATs    DB 2        
 7 BPB_RootEntCnt    DW 224    
 8 BPB_TotSec16    DW 2880        
 9 BPB_Media    DB 0xF0        
10 BPB_FATSz16    DW 9        
11 BPB_SecPerTrk    DW 18        
12 BPB_NumHeads    DW 2        
13 BPB_HiddSec    DD 0    
14 BPB_TotSec32    DD 0    
15 
16 
17 BS_DrvNum    DB 0        
18 BS_Reserved1    DB 0         
19 BS_BootSig    DB 29h    
20 BS_VolID    DD 0         
21 BS_VolLab    DB 'Tinix0.01  '
22 BS_FileSysType    DB 'FAT12   '    
23 
24 FATSz            equ    9     
25 RootDirSectors        equ    14    
26 
27 SectorNoOfRootDirectory    equ    19     
28 SectorNoOfFAT1        equ    1     
29 DeltaSectorNo        equ    17     
30                      

  boot.asm :

  1 org  07c00h        
  2 
  3 BaseOfStack        equ    07c00h 
  4 BaseOfLoader        equ    09000h
  5 OffsetOfLoader        equ    0100h
  6 
  7     jmp short LABEL_START 
  8     nop        
  9     
 10 
 11 %include    "fat12hdr.inc"
 12 
 13 LABEL_START:    
 14     mov    ax, cs
 15     mov    ds, ax
 16     mov    es, ax
 17     mov    ss, ax
 18     mov    sp, BaseOfStack
 19 
 20     
 21     mov    ax, 0600h        
 22     mov    bx, 0700h     
 23     mov    cx, 0         
 24     mov    dx, 0184fh     
 25     int    10h         
 26 
 27     mov    dh, 0         
 28     call    DispStr         
 29     
 30     xor    ah, ah     
 31     xor    dl, dl 
 32     int    13h    
 33 
 34     mov    word [wSectorNo], SectorNoOfRootDirectory
 35 LABEL_SEARCH_IN_ROOT_DIR_BEGIN:
 36     cmp    word [wRootDirSizeForLoop], 0    
 37     jz    LABEL_NO_LOADERBIN        
 38     dec    word [wRootDirSizeForLoop]    
 39     mov    ax, BaseOfLoader
 40     mov    es, ax         
 41     mov    bx, OffsetOfLoader     
 42     mov    ax, [wSectorNo]    
 43     mov    cl, 1
 44     call    ReadSector
 45 
 46     mov    si, LoaderFileName     
 47     mov    di, OffsetOfLoader     
 48     cld
 49     mov    dx, 10h
 50 LABEL_SEARCH_FOR_LOADERBIN:
 51     cmp    dx, 0                                     
 52     jz    LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR     
 53     dec    dx                                         
 54     mov    cx, 11
 55 LABEL_CMP_FILENAME:
 56     cmp    cx, 0
 57     jz    LABEL_FILENAME_FOUND 
 58 dec    cx
 59     lodsb             
 60     cmp    al, byte [es:di]
 61     jz    LABEL_GO_ON
 62     jmp    LABEL_DIFFERENT         
 63     
 64 LABEL_GO_ON:
 65     inc    di
 66     jmp    LABEL_CMP_FILENAME     
 67 
 68 LABEL_DIFFERENT:
 69     and    di, 0FFE0h                     
 70     add    di, 20h                         
 71     mov    si, LoaderFileName                     
 72     jmp    LABEL_SEARCH_FOR_LOADERBIN
 73 
 74 LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR:
 75     add    word [wSectorNo], 1
 76     jmp    LABEL_SEARCH_IN_ROOT_DIR_BEGIN
 77 
 78 LABEL_NO_LOADERBIN:
 79     mov    dh, 2             
 80     call    DispStr             
 81 %ifdef    _BOOT_DEBUG_
 82     mov    ax, 4c00h      
 83     int    21h         
 84 %else
 85     jmp    $         
 86 %endif
 87 
 88 LABEL_FILENAME_FOUND:         
 89     mov    ax, RootDirSectors
 90     and    di, 0FFE0h     
 91     add    di, 01Ah     
 92     mov    cx, word [es:di]
 93     push    cx             
 94     add    cx, ax
 95     add    cx, DeltaSectorNo     
 96     mov    ax, BaseOfLoader
 97     mov    es, ax             
 98     mov    bx, OffsetOfLoader     
 99     mov    ax, cx
100 
101 LABEL_GOON_LOADING_FILE:
102     push    ax        
103     push    bx             
104     mov    ah, 0Eh         
105     mov    al, '.'            
106     mov    bl, 0Fh            
107     int    10h         
108     pop    bx        
109     pop    ax             
110 
111     mov    cl, 1
112     call    ReadSector
113     pop    ax         
114     call    GetFATEntry
115     cmp    ax, 0FFFh
116     jz    LABEL_FILE_LOADED
117     push    ax         
118     mov    dx, RootDirSectors
119     add    ax, dx
120     add    ax, DeltaSectorNo
121     add    bx, [BPB_BytsPerSec]
122     jmp    LABEL_GOON_LOADING_FILE
123 LABEL_FILE_LOADED:
124 
125     mov    dh, 1            
126     call    DispStr            
127     
128     
129     jmp    BaseOfLoader:OffsetOfLoader    
130     
131     
132 wRootDirSizeForLoop    dw    RootDirSectors     
133 wSectorNo        dw    0        
134 bOdd            db    0        
135 
136 
137 LoaderFileName        db    "LOADER  BIN", 0 
138 
139 MessageLength        equ    9
140 BootMessage:        db    "Booting  ";  
141 Message1        db    "Ready.   "; 
142 Message2        db    "No LOADER";  
143 
144 
145 DispStr:
146     mov    ax, MessageLength
147     mul    dh
148     add    ax, BootMessage
149     mov    bp, ax            
150     mov    ax, ds            
151     mov    es, ax            
152     mov    cx, MessageLength     
153     mov    ax, 01301h         
154     mov    bx, 0007h         
155     mov    dl, 0
156     int    10h             
157     ret
158 
159  
160 ReadSector:
161     push    bp
162     mov    bp, sp
163     sub    esp, 2             
164 
165     mov    byte [bp-2], cl
166     push    bx         
167     mov    bl, [BPB_SecPerTrk]    
168     div    bl             
169     inc    ah             
170     mov    cl, ah     
171     mov    dh, al             
172     shr    al, 1             
173     mov    ch, al         
174     and    dh, 1         
175     pop    bx         
176     
177     mov    dl, [BS_DrvNum]         
178 .GoOnReading:
179     mov    ah, 2            
180     mov    al, byte [bp-2]        
181     int    13h
182     jc    .GoOnReading        
183     
184     add    esp, 2
185     pop    bp
186 
187     ret
188 
189 GetFATEntry:
190     push    es
191     push    bx
192     push    ax
193     mov    ax, BaseOfLoader     
194     sub    ax, 0100h         
195     mov    es, ax             
196     pop    ax
197     mov    byte [bOdd], 0
198     mov    bx, 3
199     mul    bx         
200     mov    bx, 2
201     div    bx             
202     cmp    dx, 0
203     jz    LABEL_EVEN
204     mov    byte [bOdd], 1
205 LABEL_EVEN:
206     xor    dx, dx         
207     mov    bx, [BPB_BytsPerSec]
208     div    bx            
209     
210     push    dx
211     mov    bx, 0             
212     add    ax, SectorNoOfFAT1     
213     mov    cl, 2
214     call    ReadSector         
215     pop    dx
216     add    bx, dx
217     mov    ax, [es:bx]
218     cmp    byte [bOdd], 1
219     jnz    LABEL_EVEN_2
220     shr    ax, 4
221 LABEL_EVEN_2:
222     and    ax, 0FFFh
223 
224 LABEL_GET_FAT_ENRY_OK:
225 
226     pop    bx
227     pop    es
228     ret
229     
230 times     510-($-$$)    db    0    
231 dw     0xaa55                

  loader.asm:

  1 org  0100h
  2  
  3 BaseOfStack        equ    0100h
  4 
  5 BaseOfKernelFile    equ     08000h     
  6 OffsetOfKernelFile    equ         0h    
  7 
  8     jmp    LABEL_START        
  9 
 10 
 11 %include    "fat12hdr.inc"
 12 
 13 
 14 LABEL_START:             
 15     mov    ax, cs
 16     mov    ds, ax
 17     mov    es, ax
 18     mov    ss, ax
 19     mov    sp, BaseOfStack
 20 
 21     mov    dh, 0         
 22     call    DispStr             
 23 
 24     
 25     mov    word [wSectorNo], SectorNoOfRootDirectory    
 26     xor    ah, ah 
 27     xor    dl, dl 
 28     int    13h    
 29 LABEL_SEARCH_IN_ROOT_DIR_BEGIN:
 30     cmp    word [wRootDirSizeForLoop], 0     
 31     jz    LABEL_NO_KERNELBIN         
 32     dec    word [wRootDirSizeForLoop]    
 33     mov    ax, BaseOfKernelFile
 34     mov    es, ax             
 35     mov    bx, OffsetOfKernelFile    
 36     
 37     mov    ax, [wSectorNo]         
 38     mov    cl, 1
 39     call    ReadSector
 40 
 41     mov    si, KernelFileName     
 42     mov    di, OffsetOfKernelFile     
 43     cld
 44     mov    dx, 10h
 45 LABEL_SEARCH_FOR_KERNELBIN:
 46     cmp    dx, 0                     
 47     jz    LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR     
 48     dec    dx                     
 49     mov    cx, 11
 50 LABEL_CMP_FILENAME:
 51     cmp    cx, 0             
 52     jz    LABEL_FILENAME_FOUND     
 53     dec    cx             
 54     lodsb 
 55     cmp    al, byte [es:di]     
 56     jz    LABEL_GO_ON
 57     jmp    LABEL_DIFFERENT
 58 LABEL_GO_ON:
 59     inc    di
 60     jmp    LABEL_CMP_FILENAME
 61     
 62 LABEL_DIFFERENT:
 63     and    di, 0FFE0h         
 64     add    di, 20h            
 65     mov    si, KernelFileName
 66     jmp    LABEL_SEARCH_FOR_KERNELBIN
 67     
 68 LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR:
 69     add    word [wSectorNo], 1
 70     jmp    LABEL_SEARCH_IN_ROOT_DIR_BEGIN
 71 
 72 LABEL_NO_KERNELBIN:
 73     mov    dh, 2             
 74     call    DispStr         
 75 %ifdef    _LOADER_DEBUG_
 76     mov    ax, 4c00h    
 77     int    21h            
 78 %else
 79     jmp    $         
 80 %endif
 81 
 82 LABEL_FILENAME_FOUND:             
 83     mov    ax, RootDirSectors
 84     and    di, 0FFF0h     
 85 
 86     push    eax
 87     mov    eax, [es : di + 01Ch]         
 88     mov    dword [dwKernelSize], eax 
 89     pop    eax
 90 
 91     add    di, 01Ah     
 92     mov    cx, word [es:di]
 93     push    cx         
 94     add    cx, ax
 95     add    cx, DeltaSectorNo
 96     mov    ax, BaseOfKernelFile
 97     mov    es, ax        
 98     mov    bx, OffsetOfKernelFile    
 99     mov    ax, cx         
100 
101 LABEL_GOON_LOADING_FILE:
102     push    ax         
103     push    bx             
104     mov    ah, 0Eh             
105     mov    al, '.'            
106     mov    bl, 0Fh             
107     int    10h         
108     pop    bx        
109     pop    ax         
110 
111     mov    cl, 1
112     call    ReadSector
113     pop    ax         
114     call    GetFATEntry
115     cmp    ax, 0FFFh
116     jz    LABEL_FILE_LOADED
117     push    ax             
118     mov    dx, RootDirSectors
119     add    ax, dx
120     add    ax, DeltaSectorNo
121     add    bx, [BPB_BytsPerSec]
122     jmp    LABEL_GOON_LOADING_FILE
123 LABEL_FILE_LOADED:
124 
125     call    KillMotor         
126 
127     mov    dh, 1             
128     call    DispStr         
129 
130     jmp    $
131 
132 
133     
134 wRootDirSizeForLoop    dw    RootDirSectors
135 wSectorNo        dw    0         
136 bOdd            db    0     
137 dwKernelSize        dd    0     
138 
139 
140 KernelFileName        db    "KERNEL  BIN", 0      
141 MessageLength        equ    9
142 LoadMessage:        db    "Loading  "
143 Message1        db    "Ready.   "
144 Message2        db    "No KERNEL"
145 
146 DispStr:
147     mov    ax, MessageLength
148     mul    dh
149     add    ax, LoadMessage
150     mov    bp, ax         
151     mov    ax, ds             
152     mov    es, ax         
153     mov    cx, MessageLength     
154     mov    ax, 01301h         
155     mov    bx, 0007h     
156     mov    dl, 0
157     add    dh, 3         
158     int    10h         
159     ret
160     
161 ReadSector:
162  
163     push    bp
164     mov    bp, sp
165     sub    esp, 2         
166 
167     mov    byte [bp-2], cl
168     push    bx             
169     mov    bl, [BPB_SecPerTrk]     
170     div    bl             
171     inc    ah        
172     mov    cl, ah            
173     mov    dh, al            
174     shr    al, 1             
175     mov    ch, al             
176     and    dh, 1             
177     pop    bx
178     
179     mov    dl, [BS_DrvNum]         
180 .GoOnReading:
181     mov    ah, 2            
182     mov    al, byte [bp-2]         
183     int    13h
184     jc    .GoOnReading        
185     
186     add    esp, 2
187     pop    bp
188 
189     ret 
190     
191 GetFATEntry:
192     push    es
193     push    bx
194     push    ax
195     mov    ax, BaseOfKernelFile 
196     sub    ax, 0100h         
197     mov    es, ax            
198     pop    ax
199     mov    byte [bOdd], 0
200     mov    bx, 3
201     mul    bx         
202     mov    bx, 2
203     div    bx         
204     cmp    dx, 0
205     jz    LABEL_EVEN
206     mov    byte [bOdd], 1
207 LABEL_EVEN:
208     xor    dx, dx             
209     mov    bx, [BPB_BytsPerSec]
210     div    bx            
211     
212     push    dx
213     mov    bx, 0         
214     add    ax, SectorNoOfFAT1     
215     mov    cl, 2
216     call    ReadSector         
217     pop    dx
218     add    bx, dx
219     mov    ax, [es:bx]
220     cmp    byte [bOdd], 1
221     jnz    LABEL_EVEN_2
222     shr    ax, 4
223 LABEL_EVEN_2:
224     and    ax, 0FFFh
225 
226 LABEL_GET_FAT_ENRY_OK:
227 
228     pop    bx
229     pop    es
230     ret
231     
232 KillMotor:
233     push    dx
234     mov    dx, 03F2h
235     mov    al, 0
236     out    dx, al
237     pop    dx
238     ret 

 

  加载功能已经有了,但是还没有内核给以上程序拿来加载。

  我们来实现一个最简单的内核,以后会基于此扩展。

  kernel.asm :

    此处的K不会打印,因为这里只是假设gs指向了显存。

1 [section .text]
2 
3 global _start     
4 
5 _start: 
6     mov    ah, 0Fh                ; 0000: 黑底    1111: 白字
7     mov    al, 'K'
8     mov    [gs:((80 * 1 + 39) * 2)], ax    ; 屏幕第 1 行, 第 39 列。
9     jmp    $

  

  出现了Ready,说明我们的kernel内核已经加载成功了。

 

目录
相关文章
|
1月前
|
存储 物联网 调度
操作系统的心脏:内核深度解析
在数字世界的构建中,操作系统扮演着基石的角色,而其核心—内核,则是这一复杂系统的灵魂。本文将深入探讨操作系统内核的工作原理,揭示它是如何管理硬件资源、运行程序以及提供系统服务的。通过理解内核的结构和功能,我们可以更好地把握计算机系统的运作机制,进而优化和创新我们的技术实践。
|
7天前
|
缓存 监控 网络协议
Linux操作系统的内核优化与实践####
本文旨在探讨Linux操作系统内核的优化策略与实际应用案例,深入分析内核参数调优、编译选项配置及实时性能监控的方法。通过具体实例讲解如何根据不同应用场景调整内核设置,以提升系统性能和稳定性,为系统管理员和技术爱好者提供实用的优化指南。 ####
|
12天前
|
存储 Linux 开发者
探索操作系统的内核——从理论到实践
操作系统是计算机科学的核心,它像一位默默无闻的指挥官,协调着硬件和软件之间的复杂关系。本文将深入操作系统的心脏——内核,通过直观的解释和丰富的代码示例,揭示其神秘面纱。我们将一起学习进程管理、内存分配、文件系统等关键概念,并通过实际代码,体验内核编程的魅力。无论你是初学者还是有经验的开发者,这篇文章都将带给你新的视角和知识。
|
15天前
|
存储 调度 开发者
探索操作系统的心脏:内核与用户空间的交互之旅
在数字世界的无限广阔中,操作系统扮演着枢纽的角色,连接硬件与软件,支撑起整个计算生态。本篇文章将带领读者深入操作系统的核心——内核,揭示其与用户空间的神秘交互。我们将透过生动的例子和易于理解的比喻,深入浅出地探讨这一复杂主题,旨在为非专业读者揭开操作系统的神秘面纱,同时为有一定基础的读者提供更深层次的认识。从进程管理到内存分配,从文件系统到设备驱动,每一个环节都是精确而优雅的舞蹈,它们共同编织出稳定而高效的计算体验。让我们开始这场奇妙之旅,一探操作系统背后的科学与艺术。
22 5
|
18天前
|
安全 数据处理 调度
探索操作系统的心脏:内核与用户空间的交互之旅
操作系统,这个现代计算机体系的守门人,承载着软件与硬件间复杂而精妙的对话。本文将深入其核心,揭秘内核与用户空间之间如何协同工作,确保数据安全且高效地流动。我们将透过代码示例的镜头,观察这一过程的具体实现,同时反思在设计与使用操作系统时面临的挑战与机遇。
|
20天前
|
存储 算法 调度
探索操作系统的心脏:内核设计与实现
在数字世界的庞大机器中,操作系统扮演着至关重要的角色。本文将深入浅出地探讨操作系统的核心——内核的设计原理与实现细节。我们将从内核的概念出发,逐步深入到内核的各个组成部分,包括进程管理、内存管理、文件系统以及输入输出系统的工作机制。通过本文,读者不仅能够了解操作系统内核的基本框架,还将掌握如何通过编程实践加深对操作系统核心概念的理解。让我们一起揭开操作系统内核的神秘面纱,探索它的精妙设计,并体会编程实践中的乐趣和挑战。
45 2
|
26天前
|
缓存 资源调度 安全
深入探索Linux操作系统的心脏——内核配置与优化####
本文作为一篇技术性深度解析文章,旨在引领读者踏上一场揭秘Linux内核配置与优化的奇妙之旅。不同于传统的摘要概述,本文将以实战为导向,直接跳入核心内容,探讨如何通过精细调整内核参数来提升系统性能、增强安全性及实现资源高效利用。从基础概念到高级技巧,逐步揭示那些隐藏在命令行背后的强大功能,为系统管理员和高级用户打开一扇通往极致性能与定制化体验的大门。 --- ###
58 9
|
29天前
|
存储 人工智能 安全
操作系统的心脏——内核深度解析
【10月更文挑战第29天】 本文深入探讨了操作系统的核心组件——内核,包括其定义、功能、架构以及在现代计算中的重要性。通过对比不同操作系统内核的设计哲学和技术实现,揭示了内核如何影响系统性能、稳定性和安全性。此外,文章还讨论了未来内核技术的潜在发展方向,为读者提供了一个全面了解内核工作原理的平台。
|
26天前
|
存储 消息中间件 算法
深入探索操作系统的心脏——内核机制解析
本文旨在揭示操作系统核心——内核的工作原理,通过剖析其关键组件与机制,为读者提供一个清晰的内核结构图景。不同于常规摘要的概述性内容,本文摘要将直接聚焦于内核的核心概念、主要功能以及其在系统管理中扮演的角色,旨在激发读者对操作系统深层次运作原理的兴趣与理解。
|
26天前
|
缓存 运维 网络协议
深入Linux内核架构:操作系统的核心奥秘
深入Linux内核架构:操作系统的核心奥秘
46 2