30天自制操作系统(第四天)

8086- 80286- 80386- 80486- Pentium- Pentium Pro- Pentium 1- Pentium 2- Pentium 3 到80286都是16位CPU,其他是32位CPU

p=(char *)i; *p=i&0x0f;

改写成汇编语言就是: MOV ECX,i MOV BYTE [ECX],(i&0x0f) 具体件书72到74页,从汇编角度看,有助于更好的理解C语言的指针

p[i]与*(p+i)的意思完全相同,不是说改变一下写法,地址变量就变成数组了,不能被那些 劣质的教科书骗了,加法具有交换律,所以*(p+i)==*(i+p),因此p[i]与i[p]是等价的,比 说a[2]与2[a]是等价的

RGB调色板各种颜色及其对应的代码,书76页

cpu的管脚不仅与内存相连,还与设备相连

调色板的访问步骤(重点内容) 1.首先将一连串的访问中屏蔽中断 2,将想要设定的调色板号码写入0x03c8,紧接着,按照R,G,B的顺序写入0x03c9.如果还想继续 设定下一调色板,则省略调色板号码,在按照RGB的顺序写入0x03c9就行了 3.如果想要读出当前调色板状态,首先将调色板的号码写入0x03c7,在从0x03c9读取3次,读出的顺序 就是R,G,B.如果继续读出下一个调色板,同样也是省略调色板号码的设定,按RGB顺序读出

中断标志,只能读入eflags寄存器的第9位,进位标志是第0位

只能用pushfd,popfd指令来读写eflags

下面是第四天代码

;hello-os
;TAB=4

CYLS    EQU        10
    ORG     0X7C00          ;指明程序的装载地址  

;以下这段是标准FAT12格式软盘专用代码
     JMP     entry
    DB        0x90
    DB        "HARIBOTE"      ;启动扇区的名称可以使任意的字符串
    DW        512                ;每个扇区的大小(必须为512字节)
    DB        1               ;簇的大小(必须为1个扇区)
    DW        1                ;FAT的起始位置(一般从第一个扇区开始)
    DB        2                ;FAT的个数(必须为2)
    DW        224                ;根目录的大小(一般设置为224)
    DW        2880            ;该磁盘的大小(必须是2880扇区)
    DB        0xf0            ;磁盘的种类(必须是0xf0)
    DW        9                ;FAT的长度(必须是9扇区)
    DW        18                ;1个磁道有几个扇区(必须是18)
    DW        2               ;磁头数(必须是2)
    DD        0               ;不试用分区(必须是0)
    DD        2880            ;重写一次磁盘大小
    DB        0,0,0x29        ;固定
    DD        0xffffffff      ;(可能是)卷码标号
    DB        "HARIBOTEOS "      ;磁盘的名称(11字节)
    DB        "FAT12   "        ;磁盘格式的名称(8字节)
    RESB    18              ;先空出18字节

;程序核心

entry:
    MOV     AX,0         ;初始化寄存器
    MOV     SS,AX
    MOV     SP,0x7c00
    MOV     DS,AX

    MOV     AX,0x0820
    MOV     ES,AX
    MOV     CH,0          ;柱面0
    MOV     DH,0          ;磁头0
    MOV     CL,2          ;扇区2

readloop:
    MOV        SI,0         ;记录失败次数的寄存器

retry:
    MOV        AH,0x02       ;AH=0x02  :  读盘
    MOV     AL,1          ;一个扇区
    MOV     BX,0
    MOV     DL,0x00        ;A驱动器
    INT     0x13           ;调用磁盘BIOS
    JNC     next            ;没出错的话就跳转到next
    ADD        SI,1
    CMP     SI,5
    JAE        error           ;SI>=5跳转到error
    MOV     AH,0x00
    MOV     DL,0x00         ;A驱动器
    INT     0x13            ;重置驱动器
    JMP     retry

next:
    MOV     AX,ES           ;把内存地址后移0x200
    ADD        AX,0x0020
    MOV     ES,AX            ;因为没有ADD ES,0x200指令
    ADD     CL,1             ;往CL里面加1
    CMP     CL,18
    JBE        readloop         ;如果CL<=18,跳转至readloop
    MOV     CL,1
    ADD     DH,1
    CMP     DH,2
    JB        readloop          ;如果DH<=2,跳转到readloop
    MOV     DH,0
    ADD     CH,1
    CMP        CH,CYLS
    JB        readloop           ;如果CH<CYLS,则跳转到readloop
    MOV        [0x0ff0],CH
    JMP     0xc200

error:
    MOV     SI,msg

putloop:
    MOV     AL,[SI]
    ADD     SI,1          ;给SI加1
    CMP        AL,0
    JE        fin
    MOV        AH,0x0e     ;显示一个文字
    MOV      BX,15       ;指定字符颜色
    INT      0x10        ;调用显卡BIOS
    JMP      putloop

fin:
    HLT                 ;让CPU停止循环,等待指令
    JMP      fin        ;无限循环

msg:
    DB        0X0a,0X0a   ;换行两次
    DB        "load error"
    DB        0x0a
    DB        0
    RESB    0x7dfe-$          ;填写0x00,直到0x001fe
    DB        0x55, 0xaa
 1 ;naskfunc
 2 ;TAB=4
 3
 4 [FORMAT "WCOFF"]  ;制作目标文件的模式
 5 [INSTRSET "i486p"]   ;告诉nsk这个指令是i486
 6 [BITS 32]          ;制作32位模式用的机械语言
 7
 8 ;制作目标文件的信息
 9 [FILE "naskfunc.nas"]   ;源文件名信息
10     GLOBAL    _io_hlt, _io_cli, _io_sti, _io_stihlt
11     GLOBAL    _io_in8,  _io_in16,  _io_in32
12     GLOBAL    _io_out8, _io_out16, _io_out32
13     GLOBAL    _io_load_eflags, _io_store_eflags
14    ;程序中包含的函数名
15
16 ;以下是实际函数
17
18 [SECTION .text]     ;目标文件中写了这些之后在写程序
19 _io_hlt:    ; void io_hlt(void);
20         HLT
21         RET
22
23 _io_cli:    ; void io_cli(void);
24         CLI
25         RET
26
27 _io_sti:    ; void io_sti(void);
28         STI
29         RET
30
31 _io_stihlt:    ; void io_stihlt(void);
32         STI
33         HLT
34         RET
35
36 _io_in8:    ; int io_in8(int port);
37         MOV        EDX,[ESP+4]        ; port
38         MOV        EAX,0
39         IN        AL,DX
40         RET
41
42 _io_in16:    ; int io_in16(int port);
43         MOV        EDX,[ESP+4]        ; port
44         MOV        EAX,0
45         IN        AX,DX
46         RET
47
48 _io_in32:    ; int io_in32(int port);
49         MOV        EDX,[ESP+4]        ; port
50         IN        EAX,DX
51         RET
52
53 _io_out8:    ; void io_out8(int port, int data);
54         MOV        EDX,[ESP+4]        ; port
55         MOV        AL,[ESP+8]        ; data
56         OUT        DX,AL
57         RET
58
59 _io_out16:    ; void io_out16(int port, int data);
60         MOV        EDX,[ESP+4]        ; port
61         MOV        EAX,[ESP+8]        ; data
62         OUT        DX,AX
63         RET
64
65 _io_out32:    ; void io_out32(int port, int data);
66         MOV        EDX,[ESP+4]        ; port
67         MOV        EAX,[ESP+8]        ; data
68         OUT        DX,EAX
69         RET
70
71 _io_load_eflags:    ; int io_load_eflags(void);
72         PUSHFD        ; PUSH EFLAGS
73         POP        EAX
74         RET
75
76 _io_store_eflags:    ; void io_store_eflags(int eflags);
77         MOV        EAX,[ESP+4]
78         PUSH    EAX
79         POPFD        ; POP EFLAGS
80         RET
  1 /*告诉C编译器,有一个函数在别的文件里面*/
  2 void io_hlt(void);
  3 void io_cli(void);
  4 void io_out8(int port, int data);
  5 int io_load_eflags(void);
  6 void io_store_eflags(int eflags);
  7
  8
  9 //就算是写在同一个文件里面,如果想在定义前使用,还是必须事先申明一下
 10 void init_palette(void);
 11 void set_palette(int start, int end, unsigned char *rgb);
 12 void boxfill8(unsigned char *vram,int xsize,unsigned char c,int x0,int y0,int x1,int y1);
 13
 14 #define COL8_000000     0
 15 #define COL8_FF0000     1
 16 #define COL8_00FF00     2
 17 #define COL8_FFFF00     3
 18 #define COL8_0000FF     4
 19 #define COL8_FF00FF     5
 20 #define COL8_00FFFF     6
 21 #define COL8_FFFFFF     7
 22 #define COL8_C6C6C6     8
 23 #define COL8_840000     9
 24 #define COL8_008400     10
 25 #define COL8_848400     11
 26 #define COL8_000084     12
 27 #define COL8_840084     13
 28 #define COL8_008484     14
 29 #define COL8_848484     15
 30
 31 void HariMain(void)
 32 {
 33     //int i;   /*变量申明*/
 34     char *vram;   /*这是地址调用*/
 35     int xsize,ysize;
 36
 37     init_palette();/*设定调色板*/
 38     vram=(char *) 0xa0000;   /*给地址变量赋初值*/
 39     xsize=320;
 40     ysize=200;
 41
 42     boxfill8(vram, xsize, COL8_008484,  0,         0,          xsize -  1, ysize - 29);
 43     boxfill8(vram, xsize, COL8_C6C6C6,  0,         ysize - 28, xsize -  1, ysize - 28);
 44     boxfill8(vram, xsize, COL8_FFFFFF,  0,         ysize - 27, xsize -  1, ysize - 27);
 45     boxfill8(vram, xsize, COL8_C6C6C6,  0,         ysize - 26, xsize -  1, ysize -  1);
 46
 47     boxfill8(vram, xsize, COL8_FFFFFF,  3,         ysize - 24, 59,         ysize - 24);
 48     boxfill8(vram, xsize, COL8_FFFFFF,  2,         ysize - 24,  2,         ysize -  4);
 49     boxfill8(vram, xsize, COL8_848484,  3,         ysize -  4, 59,         ysize -  4);
 50     boxfill8(vram, xsize, COL8_848484, 59,         ysize - 23, 59,         ysize -  5);
 51     boxfill8(vram, xsize, COL8_000000,  2,         ysize -  3, 59,         ysize -  3);
 52     boxfill8(vram, xsize, COL8_000000, 60,         ysize - 24, 60,         ysize -  3);
 53
 54     boxfill8(vram, xsize, COL8_848484, xsize - 47, ysize - 24, xsize -  4, ysize - 24);
 55     boxfill8(vram, xsize, COL8_848484, xsize - 47, ysize - 23, xsize - 47, ysize -  4);
 56     boxfill8(vram, xsize, COL8_FFFFFF, xsize - 47, ysize -  3, xsize -  4, ysize -  3);
 57     boxfill8(vram, xsize, COL8_FFFFFF, xsize -  3, ysize - 24, xsize -  3, ysize -  3);
 58
 59     for(;;){
 60     io_hlt();
 61     /*这里想写上HLT,但C语言中不用HLT!*/
 62     }
 63 }
 64
 65 void init_palette(void)
 66 {
 67     static unsigned char table_rgb[16*3]={
 68         0x00,0x00,0x00,   //0.黑色
 69         0xff,0x00,0x00,   //1.亮红
 70         0x00,0xff,0x00,   //2.亮绿
 71         0xff,0xff,0x00,   //3.亮黄
 72         0x00,0x00,0xff,    //4.亮蓝
 73         0xff,0x00,0xff,    //5.亮紫
 74         0x00,0xff,0xff,    //6.浅亮蓝
 75         0xff,0xff,0xff,    //7.白
 76         0xc6,0xc6,0xc6,    //8.亮灰
 77         0x84,0x00,0x00,    //9.暗红
 78         0x00,0x84,0x00,    //10.暗绿
 79         0x84,0x84,0x00,    //11.暗黄
 80         0x00,0x00,0x84,    //12.暗青
 81         0x84,0x00,0x84,   //13.暗紫
 82         0x00,0x84,0x84,    //14.浅暗蓝
 83         0x84,0x84,0x84    //15.暗灰
 84     };
 85     set_palette(0,15,table_rgb);
 86     return;
 87     /*C语言中,static char语句只能用于数据,相当于汇编中的DB*/
 88 }
 89
 90 void set_palette(int start,int end,unsigned char *rgb)
 91 {
 92     int i,eflags;
 93     eflags=io_load_eflags();  //记录中断许可标志的值
 94     io_cli();                 //将中断标志置为0,静止中断
 95     io_out8(0x03c8,start);    //调色板号写入0x03c8
 96     for(i=start;i<=end;i++)
 97     {
 98         io_out8(0x03c9,rgb[0]/4);
 99         io_out8(0x03c9,rgb[1]/4);
100         io_out8(0x03c9,rgb[2]/4);
101         rgb+=3;
102     }
103     io_store_eflags(eflags);  /*复原中断许可标志*/
104     return;
105 }
106
107 void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1)  //给对应地址填色,循环画出对应的矩形框
108 {
109     int x, y;
110     for (y = y0; y <= y1; y++) {
111         for (x = x0; x <= x1; x++)
112             vram[y * xsize + x] = c;
113     }
114     return;
115 }
时间: 2025-01-13 09:33:26

30天自制操作系统(第四天)的相关文章

《30天自制操作系统》读书笔记(2)hello, world

让系统跑起来 要写一个操作系统,我们首先要有一个储存系统的介质,原版书似乎是06年出版的,可惜那时候没有电脑,没想到作者用的还是软盘,现在的电脑谁有软驱?不得已我使用一张128M的SD卡来代替,而事实上你用的是U盘还是软盘对我们的操作系统没有影响,缺点是你的U盘刷入系统后容量只能是1440 MB,即当年流行的3.5英寸软盘的大小,当然不用担心,再格式化一次(用DiskGeniu),就可以恢复. 我做事情的话,总是怕自己的努力的结果白费了,害怕辛辛苦苦看完这本书但是发现做出来的东西现在根本没法用,

《30天自制操作系统》读书笔记(4) 绘图

暑假果然是滋生懒散的温床. (╯‵□′)╯︵┻━┻ 好久不动都忘记之前做到哪里了, 上次好像做到了C语言的引入, 这一节所做的东西都相当轻松, 将会绘制出操作系统的基本界面. 绘图的原理 按照书中所说, 将值写入到显存中就能在屏幕上显示相应的像素, 在asmhead.nas 中有这一段: 1 CYLS EQU 0x0ff0 ; 设定启动区 2 LEDS EQU 0x0ff1 3 VMODE EQU 0x0ff2 ; 关于颜色数目的信息,颜色的位数 4 SCRNX EQU 0x0ff4 ; 分辨率

《30天自制操作系统》——虚拟机使用

<30天自制操作系统>是一本学习操作系统的好教材,它教我们怎么从建立引导区开始,从零实现一个操作系统.但是,实现书中例子的时候,我们需要不断将我们写好的操作系统代码写入软盘并且还要不断重启电脑来试验我们的代码,大家一定感到很头疼吧. 与其不停的重启,不如使用模拟器,向大家推荐一款模拟器qemu,它是由Fabrice Bellard编写,功能非常强大.那么下面我就来教大家使用qemu运行书中自制操作系统的方法吧. 一.安装qemu 我使用的是苹果笔记本,苹果有一个非常好用的程序管理工具叫brew

30天自制操作系统之第12天 定时器

定时器的中断处理程序要保证高效率,需要进行一些优化,这里介绍优化的方法.对于一个操作系统来说,会有多个定时器,假设该操作系统维护了500个定时器,当每一次定时中断发生时(这里我们设定1秒发生100次中断),调用中断处理程序,中断处理程序会对这500个定时器进行if判断,看哪些正在被使用,这样1秒内,就会有500X100=10000次if判断,而中断处理程序最讲究节省时间.实际上,我们不必每发生一次定时中断就去对这500个定时器进行判断.因为假设我们使用了500个定时器中的10个,而10个定时器中

关于U盘启动操作系统《30天自制操作系统》

原本的启动是从img启动的,并且这个img是用FAT12文件系统进行格式化的(详细去搜索FAT12文件格式,这里给大家推荐一篇http://www.doc88.com/p-646605198560.html),那么也就是说我们的img文件符合FAT12文件系统的格式了.接下来我们用winhex这个软件来查看我们的img文件,同一时候比对FAT12文件系统的格式,看是否我们的img文件同FAT12文件系统描写叙述的同样: 从上图中能够看到里面有一个haribotesys的文件夹项.那么我们看看我们

《30天自制操作系统》U盘启动,真机运行(16天)

首先说一下到目前为止U盘启动遇到的问题,首先的一个问题是"system volume information",目前尚未解决,这个问题可能导致U盘启动失败,我猜测可能是由于每一次重新将OS写到U盘的时候原来的信息没有被清除,导致了在执行的时候把那些没有被覆盖掉的信息当成指令执行了.这个问题我会继续的追踪下去,力求能找到引起这个问题的真正原因是什么,如果有遇到同样问题的朋友,能留言相告. 下面是真机的运行截图(当然纯属装逼,哈哈) 下面还是展示ipl10.nas代码 ; haribote

多定时器处理1(30天自制操作系统--读书笔记)

自认为写过很多MCU程序,但总是回头想想,我所了解的MCU编程思想大体有两种,其中具体的想法我得再找时间写下来. 总想总结出一个可扩展的,易移植的写法,但能力还没到这个层次.但<30天自制操作系统>这本书确实给我了一个思路,就像我已经写过的两篇读书笔记. 将两个独立的内容--FIFO和内存动态管理做到高度模块化,尤其是其中数据结构模型的设计更是我学习的好例子. 今天要学习的设计内容是多定时器处理.原书对这部分的处理讲的很详细,由浅入深,看得我由衷佩服作者,也可能是因为我水平低,稍稍看出点门道来

内存管理(30天自制操作系统--读书笔记)

今天继续读书笔记,“挑战内存管理”(30天自制操作系统). 为什么对这块内容敢兴趣呢,因为曾经遇到这么一个问题.在STM32程序中想使用队列,可不是上篇讲的FIFO,而是使用了较大的内存空间,又想做队列的顺序存取管理. 在这个队列里用到了malloc,动态申请内存,一开始是直接申请不到内存,后来在启动脚本里更改了设置堆的地址值,可以申请成功,但发现申请几次后,也申请不到内存. 果然MCU级别的程序,内存这块处理起来就没有windows程序那么随心所欲了.讲了这么多,开始正题吧. 1.相关数据结构

单字节的FIFO缓存(30天自制操作系统--读书笔记)

从今天起,写一些读书笔记.最近几个月都在看<30天自制操作系统这本书>,书虽说看的是电子书,但可以花钱买的正版书,既然花费了金钱,就总得有些收获. 任何人都不能总是固步自封,想要进步就得学习别人的知识,对于程序员而言,最简单的方法即是学习别人的代码. 今天的标题是“单字节的FIFO缓存”,其实就是做一个FIFO,看名字就知道了.也就4个函数和1个相关结构体,这样的小代码在嵌入式系统中很常用,也会很好用. 1.相关数据结构体 struct FIFO8 { unsigned char *buf;

《30天自制操作系统》笔记(12)——多任务入门

<30天自制操作系统>笔记(12)——多任务入门 进度回顾 上一篇介绍了设置显示器高分辨率的方法.本篇讲一下操作系统实现多任务的方法. 什么是多任务 对程序员来说,也许这是废话,不过还是说清楚比较好. 多任务就是让电脑同时运行多个程序(如一边写代码一边听音乐一边下载电影). 电脑的CPU只有固定有限的那么一个或几个,不可能真的同时运行多个程序.所以就用近似的方式,让多个程序轮换着运行.当轮换速度够快(0.01秒),给人的感觉就是"同时"运行了. 多任务之不实用版 我们首先从