开发者社区> 奶berber> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

自制操作系统Antz day06——内核初步,引入c语言

简介: 在前几天的任务中,我们已经简单实现了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. GCC前提

  gcc -c -o main.o  main.c

  -c的作用是编译,汇编到目标代码,不进行链接,也就是直接生成目标文件。

  -o的作用是将输出的文件以指定文件名来存储,有同名文件会直接覆盖。

  如果你不会使用GCC,请先去略作了解。

  这行命令会生成一个main.o文件。它只是一个目标文件,也是待重定位文件,重定位是指文件里面所用的符号还没有安排地址,这些符号的地址要与其他目标文件组成一个可执行文件时再重新定位(排地址),符号是指该目标文件中所调用的函数或使用的变量,这里的组成就是指链接。

  main.o是可重定位文件,ld命令可以链接,指定最终生成文件的起始虚拟地址。

  ld main.o -Ttext 0xc0001500 -e main -o main.bin

  -Ttext指定了起始虚拟地址是0xc0001500,这个地址是内核加载需要的,-o是指定输出文件,-e是指定了程序起始地址。

 

1. 引入C语言

  内核,是一个操作系统的核心。是基于硬件的第一层软件扩充,提供操作系统的最基本的功能,是操作系统工作的基础,它负责管理系统的进程、内存、设备驱动程序、文件和网络系统,决定着系统的性能和稳定性。

  现代操作系统设计中,为减少系统本身的开销,往往将一些与硬件紧密相关的(如中断处理程序、设备驱动程序等)、基本的、公共的、运行频率较高的模块(如时钟管理、进程调度等)以及关键性数据结构独立开来,使之常驻内存,并对他们进行保护。通常把这一部分称之为操作系统的内核。
  程序可以直接地被调入计算机中执行,这样的设计说明了设计者不希望提供任何硬件抽象和操作系统的支持,它常见于早期计算机系统的设计中。最终,一些辅助性程序,例如程序加载器和调试器,被设计到机器核心当中,或者固化在只读存储器里。这些变化发生时,操作系统内核的概念就渐渐明晰起来了。

  antz_os.asm :  

  1 ; antz_os
  2 
  3 
  4 BOTPAK    EQU        0x00280000        
  5 DSKCAC    EQU        0x00100000        
  6 DSKCAC0    EQU        0x00008000        
  7 
  8 
  9 CYLS    EQU        0x0ff0            
 10 LEDS    EQU        0x0ff1
 11 VMODE    EQU        0x0ff2            
 12 SCRNX    EQU        0x0ff4           
 13 SCRNY    EQU        0x0ff6      
 14 VRAM    EQU        0x0ff8          
 15 
 16         ORG        0xc200     
 17 
 18 
 19 
 20         MOV        AL,0x13            
 21         MOV        AH,0x00
 22         INT        0x10
 23         MOV        BYTE [VMODE],8   
 24         MOV        WORD [SCRNX],320
 25         MOV        WORD [SCRNY],200
 26         MOV        DWORD [VRAM],0x000a0000
 27 
 28 
 29 
 30         MOV        AH,0x02
 31         INT        0x16             ; keyboard BIOS
 32         MOV        [LEDS],AL
 33 
 34 
 35 
 36 
 37 
 38 
 39         MOV        AL,0xff
 40         OUT        0x21,AL
 41         NOP                        
 42         OUT        0xa1,AL
 43 
 44         CLI                       
 45 
 46
 47 
 48         CALL    waitkbdout
 49         MOV        AL,0xd1
 50         OUT        0x64,AL
 51         CALL    waitkbdout
 52         MOV        AL,0xdf            ; enable A20
 53         OUT        0x60,AL
 54         CALL    waitkbdout
 55 
 56 ; 保护模式转换
 57 
 58 [INSTRSET "i486p"]            
 59 
 60         LGDT    [GDTR0]     
 61         MOV        EAX,CR0
 62         AND        EAX,0x7fffffff 
 63         OR        EAX,0x00000001  
 64         MOV        CR0,EAX
 65         JMP        pipelineflush
 66 
 67         MOV        AX,1*8            
 68         MOV        DS,AX
 69         MOV        ES,AX
 70         MOV        FS,AX
 71         MOV        GS,AX
 72         MOV        SS,AX
 73 
 74 
 75 
 76         MOV        ESI,bootpack    ;
 77         MOV        EDI,BOTPAK        ; 目标
 78         MOV        ECX,512*1024/4
 79         CALL    memcpy
 80 
 81
 82 
 83 
 84 
 85         MOV        ESI,0x7c00        ;
 86         MOV        EDI,DSKCAC        ; 目标
 87         MOV        ECX,512/4
 88         CALL    memcpy
 89 
 90 
 91 
 92         MOV        ESI,DSKCAC0+512    ;
 93         MOV        EDI,DSKCAC+512    ; 目标
 94         MOV        ECX,0
 95         MOV        CL,BYTE [CYLS]
 96         IMUL    ECX,512*18*2/4    
 97         SUB        ECX,512/4       
 98         CALL    memcpy
 99 
100 
101 
102 
103 
104 
105         MOV        EBX,BOTPAK
106         MOV        ECX,[EBX+16]
107         ADD        ECX,3          
108         SHR        ECX,2          
109         JZ        skip            
110         MOV        ESI,[EBX+20]    
111         ADD        ESI,EBX
112         MOV        EDI,[EBX+12]    
113         CALL    memcpy
114 skip:
115         MOV        ESP,[EBX+12]    
116         JMP        DWORD 2*8:0x0000001b
117 
118 waitkbdout:
119         IN         AL,0x64
120         AND         AL,0x02
121         JNZ        waitkbdout        
122         RET
123 
124 memcpy:
125         MOV        EAX,[ESI]
126         ADD        ESI,4
127         MOV        [EDI],EAX
128         ADD        EDI,4
129         SUB        ECX,1
130         JNZ        memcpy            
131         RET
132 
133 
134         ALIGNB    16
135 GDT0:
136         RESB    8                
137         DW        0xffff,0x0000,0x9200,0x00cf    
138         DW        0xffff,0x0000,0x9a28,0x0047    
139         DW        0
140 GDTR0:
141         DW        8*3-1
142         DD        GDT0
143 
144         ALIGNB    16
145 bootpack:

 

  bootpack.c:

 1 void io_hlt(void);
 2 void write_mem8(int addr,int data);
 3 
 4 void HariMain(void)
 5 {
 6     int i ;
 7     for(i=0xa0000;i<0xaffff;i++){
 8         write_mem8(i,15);
 9     }
10     for(;;){
11         io_hlt();
12     }
13 }

  func.asm: 

 1 [FORMAT "WCOFF"]            
 2 [BITS 32]                     
 3 [INSTRSET "i486p"]            
 4 
 5 [FILE "naskfunc.nas"]    
 6 
 7         GLOBAL    _io_hlt    
 8 
 9 [SECTION .text]        
10 
11 _io_hlt:    ; void io_hlt(void);
12         HLT
13         RET
14 
15 _write_mem8:
16         MOV ECX,[ESP+4]
17         MOV AL,[ESP+8]
18         MOV [ECX],AL
19         RET

  在func.asm中声明了bootpack.c中调用的函数,用于绘制屏幕,如果你还不了解怎么绘制屏幕,可以看看第三天的直接操作显卡部分。

  生成的img打开在虚拟机之后。

  

  看到这里你可能会发现,我们在c语言中定义的函数完成了屏幕绘制,在HariMain函数中的for循环将整个屏幕完成了绘制。write_mem8函数的两个参数分别控制了位置和颜色,这是图形化的一大步。

  随意修改一下参数之后,屏幕显示就是不一样的颜色了,至于怎么改,可以在for循环里面自行修改了。

 

  关于内核的知识便不再向之前一样详细概况了,推荐一本书,《Linux内核完全剖析》。

  

 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
C语言程序设计实践(OJ)-初识函数
2964: 查闰年 Description   大家知道如何判断某一年是否是闰年吗?这个问题可难坏了小编,小编在写一个查找m年到n年之间闰年的程序,却苦于判断闰年的函数不会写,据说 今天你有上机课,我就拿着这个问题来找你了–   闰年的条件是:能被4整除但不能被100整除,或能被400整除。 #include <stdio.h> int leap_ye
1571 0
《C语言及程序设计》实践参考——链表的合并
返回:贺老师课程教学链接 【项目1-链表的合并】 输入一个整数m,表示A链表的长度,再输入m个数作为A链表中的m个数据元素,建立链表A,其头指针为heada。输入一个整数n,表示B链表的长度,再输入n个数表示B链表中的n个数据元素,建立链表B,其头指针为headb。输入i、len、j,将要从单链表A中删除自第i个元素起的共len个元素,然后将单链表A插入到单链表B的第j个
1024 0
《C语言及程序设计》实践参考——改造链表
返回:贺老师课程教学链接 【项目3 - 改造链表】 下面是一个建立动态链表的程序。阅读程序,然后按要求改造程序。 #include <iostream> using namespace std; #include <stdio.h> #include <malloc.h> #define N 5 typedef struct
871 0
《C语言及程序设计》实践参考——链表版通信录
返回:贺老师课程教学链接 【项目4-链表版通信录】 利用链表存储数据,写一个通信录程序,能够记录多个联系人的编号、姓名、性别、联系电话、地址,完成数据的录入、添加、删除、修改以及查询功能。 [参考解答] 本解答自网络:链接 #include<stdio.h> #include<string.h> #include<stdlib.h>
1071 0
《C语言及程序设计》实践参考——字符串处理函数
返回:贺老师课程教学链接  实践要求 【项目4-字符串处理函数】指针是神奇的,指向整型的指针int *p1,可以操作整型数组int a[];指向字符型的指针char *p2,可以操作字符数组(字符串)char str[];更灵活的是,在函数的传递中,指针、数组名在一定程度上可以互换。请编制函数,对字符串的进行各种操作。 序 功能 用数组名作形参 用指针作形参 1 字符串str1和str
1309 0
《C语言及程序设计》实践参考——歌手大奖赛计分函数版
返回:贺老师课程教学链接  项目要求 【项目2-歌手大奖赛计分函数版】(1)在歌手大奖赛中,有n位评委为参赛的选手打分,分数为0~10分(运行时由人输入)。选手最后得分为:去掉一个最高分和一个最低分后其余分数的平均值。请编写一个程序,完成相关的功能。 要求利用一个函数void calScore(int n),对一位选手成绩的输入成绩、计算和显示实现,其中n为评委人数。这样,在main函数
1114 0
《C语言及程序设计》实践参考——大奖赛计分
返回:贺老师课程教学链接  项目要求 【项目4:大奖赛计分】  (1)基本要求:在歌手大奖赛中,有10个评委为参赛的选手打分,分数为1~10分。选手最后得分为:去掉一个最高分和一个最低分后其余8个分数的平均值。请编写一个程序实现。 #include <stdio.h> #define n 10 int main( ) { int i=1; double ave
1066 0
《C语言及程序设计》实践参考——大奖赛计分(续一)
返回:贺老师课程教学链接  项目要求 【项目1:大奖赛计分(续一)】在歌手大奖赛中,有10个评委为参赛的选手打分,分数为1~10分。请在大奖赛计分程序基础上,增加功能,若用户输入不在0-10范围内,则立即要求重输,直到正确。 [参考解答] #include <stdio.h> #define n 10 int main( ) { int i; double av
971 0
《C语言及程序设计》实践参考——Bessel函数
返回:贺老师课程教学链接  项目要求 【项目3:Bessel函数】Bessel函数Jn(X)有以下的递推关系: 编写程序,利用递推关系,由任意的n和x≠0求Jn(X)。 [参考解答] #include <stdio.h> #include <math.h> int main( ) { double jn, j0, j1, x; int n, i;
981 0
+关注
奶berber
这辈子没法做太多事情,所以每做一件事都要做到精妙绝伦
文章
问答
文章排行榜
最热
最新
相关课程
更多
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载