《30天自制操作系统》读书笔记(3) 引入C语言
这一次的学习相当曲折, 主要是因为粗心, Makefile里面的错误导致了文件生成出现各种奇奇怪怪的问题, 弄得心力交瘁, 因此制作过程还是尽量按着作者的路子来吧.
作者提供的源码的注释在中文系统下是乱码, 而且代码的分隔用了两个Tab, 在这里要处理一下:
:%s/;.*//g 删除所有的注释;
:%s/\t\t/\t 把两个Tab替换为一个Tab;
要让作者的nas文件和asm文件拥有相同的语法规则, 在_vimrc文件的最后一行添加
au BufNewFile,BufRead *.nas set filetype=asm
- 真正的IPL
之前我们写的只是软盘启动区代码, 所有代码只能放在512字节里, 根本不够用,
所以我们要利用这一段代码读入软盘的其他内容, 并将控制权移交给它, 所以叫做IPL(Initial Program Loader).
- 需要的知识点:
int 0x13 磁盘中断
AH = 0x02 ; 读盘
AH = 0x03 ; 写盘
AH = 0x04 ; 校验
AH = 0x0c ; 寻道
AH = 0x00 ;大概是重置磁盘, 配合DH = 0x00 使用
AL = 连续处理的扇区数
CH = 柱面号
CL = 扇区号
DH = 磁头号
DL = 驱动器号
ES:BX = 缓冲地址, 寻道及校验不使用
C = 0 没有错误, AH = 0;
C = 1 错误号码存入AH.
这里只会用到0x02和0x00.
软盘的结构:
用柱面(C)-磁头(H)-扇区(S) 来标识软盘上的扇区, 我们的启动扇区的标号是C0-H0-S1, 值得注意的是下一个扇区是C0-H0-S2, 这个例子里作者要读入10个柱面, 从C0-H0-S1 读到 C9-H1-S18, 这样算来应该是18*2*10 = 360 个扇区, 大小是360*512/1024 = 180 KB, 从我们现在小的可怜的需求看来, 180KB绝对够了.(按这样算的话不是一个柱面有36个扇区吗? 此处不解).
以下的代码能将软盘除启动区外开始的180KB的空间读入内存中, 起始地址是0x8200, 占用的空间是0x2d000.
- 执行软盘中的内容
编写Haribote.nas文件如下, 结构很简单:
fin:
HLT
JMP fin问题是如何把编译好的程序和IPL结合在一起?
我们可以先编译好IPL, 和之前一样做成一个img, 然后把程序写入img.
最直观的方法是把img文件写入U盘, 把程序写入U盘, 再把U盘打包成img,
虽然有些迂回, 但是我们可以借助WinHex来直接写入, 用WinHex直接打开作者做好的Haribote.img ,可以发现它的内部格式如下:
发现Haribote.SYS处在0x4200的位置处 , 这是不是真的Haribote.sys?
也从Winhex里面打开Hraibote.sys:
只有一句, F4 EB FD, 和img文件0x4200处的完全一样, 和作者的总结一样:
向一个空软盘保存文件的时候,
1.文件名会写在0x2600以后的地方(这里我没有去验证);
2.文件的内容会写入到0x4200以后的地方.
非空软盘的情况没有考虑(这里开始我们就真正意义上使用了FAT12的文件系统了, 而不是自己设计一个文件系统).
知道了这个我们就可以知道怎么调用这个程序了, 使用作者提供的edimg.exe 可以方便地将程序写入到img中, 所以Makefile也要做相应的改动, 具体看Project文件夹day3里面的e文件夹.
这个Haribote.nas 所做的只是不断HLT, 我们并不知道这段代码是否真的执行, 作者这里使用了0x10来切换画面模式, 使得光标消失,
参数是AL = 0x13, AH = 0x00, 效果是屏幕全黑, 连光标也不能看到.
我这里采用的是0x10中断的另一个功能, 能够显示带颜色的字符串, 代码如下:
; Program
ORG 0xc200 ; 加载到 0x8200 + 0x4200 – 0x200(启动区没有被读入)
MOV AX,
MOV ES,AX
MOV AX,loaded
MOV BP,AX ; ES:BP = 串地址
MOV CX, ; 串长度
MOV AX,0x1301 ;AH = 0x13,AL = 0x01
MOV BX,0x000b ; 页号BH = 0 黑底蓝字 BL = 0x0b
MOV DL,
INT 0x10
JMP fin
loaded:
DB 0x0a, 0x0a
DB "Loaded."
DB 0x0a
DB fin:
HLT
JMP fin
效果如下, 可以确定我们Haribote.sys里面的代码已经被执行.
- 进入32位模式&导入C语言*
这里作者开始用我们看不懂的东西了, 给出了一个长长的asmhead.nas, 并且表示"先跳过这一部分", 让我有点不爽, 但是毕竟不能半途而废不是? 这里的Makefile变得越来越复杂, 在这里我第一次碰到了困难, 由于粗心Makefile写少了几行, 导致编译莫名其妙地出错, 纠结了两天才发现, 抄代码都能抄错 = =, 废话略过, 作者还增加了一个Bootpack.c 大概就是我们以后的主战场了, 这里编译过程异常繁琐(作者啊你可不可以不要用你自己写的工具!? (╯‵□′)╯︵┻━┻),
以上所有的工具都是川和先生写的或者改写的(╯‵□′)╯︵┻━┻.
需要强调的是HariMain这个Main函数的函数名已经写死了, 不能够更换, 为了在C
语言里面使用HLT, (事实上现在C语言里面根本就没有函数可用), 增加naskfunc.nas.
所有文件均如下:
IPL.nas:
; hello-os
; TAB=4
; const CYLS EQU ORG 0x7c00 JMP entry
DB 0x90
DB "OS 0.01 "
DW
DB
DW
DB
DW
DW
DB 0xf0
DW
DW
DW
DD
DD
DB ,,0x29
DD 0xffffffff
DB "OS ver 0.01"
DB "FAT12 "
RESB entry:
MOV AX,
MOV SS,AX
MOV SP,0x7c00
MOV DS,AX MOV AX,0x0820 ; 缓存位置 = ES:BX
MOV ES,AX
MOV CH, ; 柱面0
MOV DH, ; 磁头0
MOV CL, ; 扇区2 readloop:
MOV SI, ; 记录失败次数 retry:
MOV AH,0x02 ; 读盘
MOV AL, ; 一个扇区
MOV BX,
MOV DL,0x00 ; 驱动器A:
INT 0x13 ; 调用磁盘中断
JNC next
ADD SI,
CMP SI, ; 失败5次跳出
JAE error
MOV AH,0x00
MOV DL,0x00 ; 指定驱动器A:
INT 0x13 ; 重置并重试
JMP retry
next:
MOV AX,ES
ADD AX,0x0020
MOV ES,AX ; 段寄存器往后移0x0020 实际偏移 0x0020*0x0010 = 0x0200 = 512d
ADD CL,
CMP CL, ; 读到18扇区
JBE readloop; <= 则跳
MOV CL,
ADD DH, ; 换一个磁头
CMP DH,
JB readloop; <则跳
MOV DH,
ADD CH, ; 柱面+1
CMP CH,CYLS
JB readloop MOV [0x0ff0],CH
JMP 0xc200 error: ; 错误提示
MOV AX,
MOV ES,AX
MOV AX,msg
MOV BP,AX ; ES:BP = 串地址
MOV CX, ; 串长度
MOV AX,0x1301 ;AH = 0x13,AL = 0x01
MOV BX,0x000c ; 页号BH = 0 黑底红字 BL = 0x0c
MOV DL,
INT 0x10 fin:
HLT
JMP fin msg:
DB 0x0a, 0x0a
DB "Load error."
DB 0x0a
DB RESB 0x7dfe-$
DB 0x55, 0xaa
Asmhead.nas:
BOTPAK EQU 0x00280000
DSKCAC EQU 0x00100000
DSKCAC0 EQU 0x00008000 CYLS EQU 0x0ff0 ; 设定启动区
LEDS EQU 0x0ff1
VMODE EQU 0x0ff2 ; 关于颜色数目的信息,颜色的位数
SCRNX EQU 0x0ff4 ; 分辨率 X(Screen X)
SCRNY EQU 0x0ff6 ; 分辨率 Y(Screen Y)
VRAM EQU 0x0ff8 ; 图像缓冲区的起始地址 ORG 0xc200 MOV AL,0x13 ; VGA 显卡
MOV AH,0x00
INT 0x10
MOV BYTE [VMODE], ; 记录画面模式
MOV WORD [SCRNX],
MOV WORD [SCRNY],
MOV DWORD [VRAM],0x000a0000 ; 取得键盘上的LED灯的状态
MOV AH,0x02
INT 0x16
MOV [LEDS],AL MOV AL,0xff
OUT 0x21,AL
NOP
OUT 0xa1,AL
CLI CALL waitkbdout
MOV AL,0xd1
OUT 0x64,AL
CALL waitkbdout
MOV AL,0xdf
OUT 0x60,AL
CALL waitkbdout [INSTRSET "i486p"] LGDT [GDTR0]
MOV EAX,CR0
AND EAX,0x7fffffff
OR EAX,0x00000001
MOV CR0,EAX
JMP pipelineflush pipelineflush:
MOV AX,*
MOV DS,AX
MOV ES,AX
MOV FS,AX
MOV GS,AX
MOV SS,AX MOV ESI,bootpack
MOV EDI,BOTPAK
MOV ECX,*/
CALL memcpy MOV ESI,0x7c00
MOV EDI,DSKCAC
MOV ECX,/
CALL memcpy MOV ESI,DSKCAC0+
MOV EDI,DSKCAC+
MOV ECX,
MOV CL,BYTE [CYLS]
IMUL ECX,**/
SUB ECX,/
CALL memcpy MOV EBX,BOTPAK
MOV ECX,[EBX+]
ADD ECX,
SHR ECX,
JZ skip
MOV ESI,[EBX+]
ADD ESI,EBX
MOV EDI,[EBX+]
CALL memcpy skip:
MOV ESP,[EBX+]
JMP DWORD *:0x0000001b waitkbdout:
IN AL,0x64
AND AL,0x02
JNZ waitkbdout
RET memcpy:
MOV EAX,[ESI]
ADD ESI,
MOV [EDI],EAX
ADD EDI,
SUB ECX,
JNZ memcpy
RET ALIGNB GDT0:
RESB
DW 0xffff,0x0000,0x9200,0x00cf
DW 0xffff,0x0000,0x9a28,0x0047
DW GDTR0:
DW *-
DD GDT0
ALIGNB
bootpack.c:
void io_hlt(void); void HariMain(void)
{ fin:
io_hlt();
goto fin;
}
Naskkfunc.nas:
;naskfunc
[FORMAT "WCOFF"] ; 制作目标文件的模式
[BITS ] ; 制作32位模式用的机械语言 ; 制作目标文件的信息 [FILE "naskfunc.nas"] ; 源文件名信息
GLOBAL _io_hlt ; 程序中包含的函数名 ; 实际的函数
[SECTION .text] ;
_io_hlt:
HLT
RET
void io_hlt(void);
void HariMain(void)
{
fin:
io_hlt();
goto fin;
}
万恶的Makefile:
TOOLPATH = ../z_tools/
INCPATH = ../z_tools/haribote/ MAKE = $(TOOLPATH)make.exe -r
NASK = $(TOOLPATH)nask.exe
CC1 = $(TOOLPATH)cc1.exe -I$(INCPATH) -Os -Wall -quiet
GAS2NASK = $(TOOLPATH)gas2nask.exe -a
OBJ2BIM = $(TOOLPATH)obj2bim.exe
BIM2HRB = $(TOOLPATH)bim2hrb.exe
RULEFILE = $(TOOLPATH)haribote/haribote.rul
EDIMG = $(TOOLPATH)edimg.exe
DEL = del
SHORTCUT = "D:\Program Files\Oracle\VirtualBox\VirtualBox.exe" --comment "OS1" --startvm "a5c4b0e6-e142-4720-98ee-056911204b29" default :
$(MAKE) install
$(MAKE) run
$(MAKE) clean ipl10.bin : ipl10.nas Makefile
$(NASK) ipl10.nas ipl10.bin ipl10.lst asmhead.bin : asmhead.nas Makefile
$(NASK) asmhead.nas asmhead.bin asmhead.lst bootpack.gas : bootpack.c Makefile
$(CC1) -o bootpack.gas bootpack.c bootpack.nas : bootpack.gas Makefile
$(GAS2NASK) bootpack.gas bootpack.nas bootpack.obj : bootpack.nas Makefile
$(NASK) bootpack.nas bootpack.obj bootpack.lst naskfunc.obj : naskfunc.nas Makefile
$(NASK) naskfunc.nas naskfunc.obj naskfucn.lst bootpack.bim : bootpack.obj naskfunc.obj Makefile
$(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map \
bootpack.obj naskfunc.obj
echo error # 3MB+64KB=3136KB bootpack.hrb : bootpack.bim Makefile
$(BIM2HRB) bootpack.bim bootpack.hrb 0 haribote.sys :asmhead.bin bootpack.hrb Makefile
copy /B asmhead.bin+bootpack.hrb haribote.sys haribote.img : ipl10.bin haribote.sys Makefile
$(EDIMG) imgin:../z_tools/fdimg0at.tek \
wbinimg src:ipl10.bin len:512 from:0 to:0 \
copy from:haribote.sys to:@: \
imgout:haribote.img install:
$(MAKE) haribote.img run :
echo Running...
$(SHORTCUT)
echo Finished clean :
-$(DEL) *.bin
-$(DEL) *.lst
-$(DEL) *.gas
-$(DEL) *.obj
-$(DEL) bootpack.nas
-$(DEL) bootpack.map
-$(DEL) bootpack.bim
-$(DEL) bootpack.hrb
-$(DEL) haribote.sys
-$(DEL) *.*~
-$(DEL) *~
echo Finished.
这次更新慢了, 下次争取早一点…
《30天自制操作系统》读书笔记(3) 引入C语言的更多相关文章
- 《30天自制操作系统》笔记(02)——导入C语言
<30天自制操作系统>笔记(02)——导入C语言 进度回顾 在上一篇,记录了计算机开机时加载IPL程序(initial program loader,一个nas汇编程序)的情况,包括IPL ...
- 单字节的FIFO缓存(30天自制操作系统--读书笔记)
从今天起,写一些读书笔记.最近几个月都在看<30天自制操作系统这本书>,书虽说看的是电子书,但可以花钱买的正版书,既然花费了金钱,就总得有些收获. 任何人都不能总是固步自封,想要进步就得学 ...
- 《30天自制操作系统》笔记(01)——hello bitzhuwei’s OS!
<30天自制操作系统>笔记(01)——hello bitzhuwei's OS! 最初的OS代码 ; hello-os ; TAB=4 ORG 0x7c00 ; 指明程序的装载地址 ; 以 ...
- 《30天自制操作系统》笔记(01)——hello bitzhuwei’s OS!【转】
转自:http://www.cnblogs.com/bitzhuwei/p/OS-in-30-days-01-hello-bitzhuwei-OS.html 阅读目录(Content) 最初的OS代码 ...
- 《30天自制操作系统》笔记(06)——CPU的32位模式
<30天自制操作系统>笔记(06)——CPU的32位模式 进度回顾 上一篇中实现了启用鼠标.键盘的功能.屏幕上会显示出用户按键.点击鼠标的情况.这是通过设置硬件的中断函数实现的,可以说硬件 ...
- 《30天自制操作系统》笔记(03)——使用Vmware
<30天自制操作系统>笔记(03)——使用Vmware 进度回顾 在上一篇,实现了用IPL加载OS程序到内存,然后JMP到OS程序这一功能:并且总结出下一步的OS开发结构.但是遇到了真机测 ...
- 《30天自制操作系统》笔记3 --- (Day2 上节)完全解析文件系统
Day2 汇编语言学习与Makefile入门 本文仅带着思路,研究源码里关于文件系统的参数 关于day2主程序部分及更多内容,请看<30天自制操作系统>笔记 导航 发现学习中的变化 源码差 ...
- 《30天自制操作系统》笔记4 --- (Day2 下节)了解如何用汇编写操作系统中的HelloWorld
关于上一节,我测试了发现3e.4c.4e都OK ,4b 4d 4f都进不去系统还把qemu卡死了. 50不会输出HelloWorld,可能需要hex偶数且在0x3e~4f区间吧.上节复制并运行命令如下 ...
- 《30天自制操作系统》笔记5 --- (Day3)
这个专题荒废了许久,今天补点东西 不够准确的小结 用汇编来开发操作系统,就是使用汇编本身的功能再加上BIOS中断提供的功能来完成功能的过程. 汇编本身的功能不够,毕竟没有外部IO,所以通过给多个寄存器 ...
随机推荐
- 视频监控之VSCloud版本计划
下个版本会加入 1.人脸检测和人脸识别功能 2. 车牌识别. https://code.google.com/p/vscloud/ 下载连接 https://sourceforge.net/proje ...
- Java调用R(三)_系统命令调用
java通过配置的系统命令Rscript直接调用R脚本. 优点:R脚本和Java代码完全分离 缺点:R中变量不能控制 1. Java本地能够成功调用. public void CallR() { Ru ...
- 完美逆向百度手机助手5.0底部菜单栏 - Android Tabhost 点击动画
先看看百度手机助手5.0的样子: 发现他是用一个CustomTabHost.java来实现底部TabHost点击效果的,很漂亮,点击Tab的时候文字会上跑,图片会从底部跑出来的一个小动画. 下面我用自 ...
- 加快maven中jar包的下载速度
maven下载jar包的默认仓库是http://my.repository.com/repo/path速度较慢,通过配置国内镜像提高下载速度 1.打开eclipse--->Window---&g ...
- js标题文字向上滚动
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xht ...
- 【转】Android开发中的SQLite事务处理,即beginTransaction()方法
使用SQLiteDatabase的beginTransaction()方法可以开启一个事务,程序执行到endTransaction() 方法时会检查事务的标志是否为成功,如果程序执行到endTrans ...
- 码表 ASCII Unicode GBK UTF-8
2017-1-3 [ASCII]一个字节(7位,128个字符,2个16进制) 不包含中文 ASCII(American Standard Code for Information Interchang ...
- Centos7+Apache2.4+php5.6+mysql5.5搭建Lamp环境——为了wordPress
最近想搭建个人博客玩玩,挑来挑去发现口碑不错的博客程序是wordpress,简称wp.虽然是学java路线的程序员,但因入行时间太短,至今没有发现较为称手开源的博客程序,如果各位大神有好的推荐,也希望 ...
- HTML 学习笔记
1HTML 标题(Heading)是通过 <h1> - <h6> 等标签进行定义的. 并且只有这6种标题,标题中加多个空格,和一个空格没区别,标题文字前后加默认空格会被去除. ...
- 简单实现图片间的切换动画 主要用到ViewPager
简单实现图片间的切换动画 主要用到ViewPagerViewPager是android扩展包v4包中的类,这个类可以让用户左右切换当前的view.ViewPager类需要一个PagerAdapter适 ...