前言:
目前你们对“flacs软件教学视频”都比较关心,我们都想要分析一些“flacs软件教学视频”的相关文章。那么小编在网上汇集了一些有关“flacs软件教学视频””的相关资讯,希望同学们能喜欢,大家快快来了解一下吧!前天制作了第一个扇区(512字节)的内容了,俗称启动区。
今天要制作第二个扇区(512字节)的内容,俗称启动程序装载区IPL(Initial Program Loader)。
制作IPL程序装载区
更新:ipl.nas文件
在entry中增加内容
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 MOV AH,0x02 ; AH=0x02 : 读盘 MOV AL,1 ; 扇区 = 1个 MOV BX,0 MOV DL,0x00 ; A驱动器 INT 0x13 ; 调用磁盘BIOS JC errorerror: MOV SI,msg
1张软盘有80个柱面,2个磁头,18个扇区(每个扇区有 512字节)。
1张软盘的容量是: 80×2×18×512 = 1 474 560 Byte = 1 440KB。
启动区:位于C0-H0-S1(CH柱面0,DH磁头0,CL扇区1的缩写)。
IPL程序装载区:位于C0-H0-S2(CH柱面0,DH磁头0,CL扇区2的缩写)。
又出现了新单词(功能)
CH
DH
CL
CH柱面
DH磁头
CL扇区
AH
AL
DL
AH=0x02;(读盘)
AH=0x03;(写盘)
AH=0x04;(校验)
AH=0x0c;(寻道)
AL=处理对象的扇区数;(只能同时处理连续的扇区)
DL=驱动器号;
JC
jump if carry
如果进位标志(carry flag)
AH==1就跳转FLACS.CF==0:没有错误.
AH==0就跳转FLAGS.CF==1:有错误,
错误号码存入AH内(与重置 (reset)功能一样)
更详细的细枝末节,大家看看书
咱们探讨漂浮在水面上的内容(水深!)
BUG无处不在
不论是软件还是硬件,bug无处不在!
读取软盘数据时会遇到读取异常,所以新增了一个功能:重试5次!!!
更新:ipl.nas文件
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 MOV SI,0 ; 记录失败次数retry: MOV AH,0x02 ; AH=0x02 : 读盘 MOV AL,1 ; 扇区 = 1个 MOV BX,0 MOV DL,0x00 ; A驱动器 INT 0x13 ; 调用磁盘BIOS JNC fin ADD SI,1 ;每次增加1,相当于x++ CMP SI,5 ;判断语句,如果SI>=5 JAE error ;如果SI>=5时,跳转到error MOV AH,0x00 MOV DL,0x00 ; A驱动器 INT 0x13 ; 重置驱动器(系统复位) JMP retryerror: MOV SI,msg
JNC
Jump if not carry 条件跳转指令 ,进位标志位0就跳转
JAE
Jump if above or equal 条件跳转指令,大于等于时跳转
第二个扇区弄好了!
设置18个扇区
话说,1张软盘有80个柱面,2个磁头,18个扇区。
既然弄完了前2个扇区,剩下的16个扇区也弄弄吧!
更新:ipl.nas文件
【记录失败次数】做成独立功能readloop增加next功能,自动填写剩余扇区
readloop: MOV SI,0 ; 记录失败次数next: MOV AX,ES ; 内存地址后移0x200 ADD AX,0x0020 ; 因为没有ADD ES,0x020指令,需要变通 MOV ES,AX ADD CL,1 ; CL=CL+1 CMP CL,18 ; 比较CL=?18 JBE readloop ; 如果CL <= 18 跳转到readloop
JBE
“jump if below or equal 跳转指令,小于等于
要读下一个扇区,只需给CL(扇区号)加1
已经把磁盘上C0-H0-S2到C0-H0- S18的512×17=8 704字节的内容,
装载到了内存的0x8200~0xa3ff处。
18个扇区弄好了
设置10个柱面
话说,1张软盘有80个柱面,2个磁头,18个扇区。
C0-H0-S18扇区的下一扇区,是磁盘反面的C0-H1-S1直到C0-H1-S18。
然后又跑到反面从C1-H0-S1开始读取扇面,直到C9-H1- S18
更新:ipl.nas内容,并把文件名改为ipl10.nas
提醒大家这个程序只能读入10个柱面
next: ;---------这是读取18个扇区的方法 MOV AX,ES ; 内存地址后移0x200 ADD AX,0x0020 MOV ES,AX ; 因为没有ADD ES,0x020指令,需要变通 ADD CL,1 ; CL=CL+1 CMP CL,18 ; 比较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
JB
jump if below 如果小于,就跳转
EQU
equal 相当于C语言的#define命令,
用来声明常数 “CYLS EQU 10”意思是“CYLS = 10” (CYLS代 表cylinders)
10个柱面就用几行代码设置好了!
正事干完了,划划水。
更新:Makefile文件
把重复的内容写到顶部,做成公共设施
使用变量时,套上$和( )
TOOLPATH = ../z_tools/MAKE = $(TOOLPATH)make.exe -rNASK = $(TOOLPATH)nask.exeEDIMG = $(TOOLPATH)edimg.exeIMGTOL = $(TOOLPATH)imgtol.comCOPY = copyDEL = del# 默认default : $(MAKE) img# 生成文件规则ipl.bin : ipl.nas Makefile $(NASK) ipl.nas ipl.bin ipl.lstharibote.img : ipl.bin Makefile $(EDIMG) imgin:../z_tools/fdimg0at.tek \ wbinimg src:ipl.bin len:512 from:0 to:0 imgout:haribote.img# 命令asm : $(MAKE) ipl.binimg : $(MAKE) haribote.imgrun : $(MAKE) img $(COPY) haribote.img ..\z_tools\qemu\fdimage0.bin $(MAKE) -C ../z_tools/qemuclean : -$(DEL) ipl.bin -$(DEL) ipl.lstsrc_only : $(MAKE) clean -$(DEL) haribote.img
一顿操作猛如虎,好像又没干什么
如果懒?不改!
开发操作系统
今天是第三天,把虚拟机复制到day3文件夹内
来看看harib00e文件夹
多了haribote.nas文件
真会起名,haribote = 哈利波特
看看内容,只有3行代码
fin: HLT JMP fin
这是休眠功能,用来省电,毕竟1度电=0.5毛,节约是传统美德!
我们要用haribote.nas生成haribote.sys 和haribote.lst
然后,用ipl.bin 和haribote.sys生成haribote.img
看到img文件了
makefile新增内容
haribote.sys : haribote.nas Makefile $(NASK) haribote.nas haribote.sys haribote.lstharibote.img : ipl.bin haribote.sys Makefile $(EDIMG) imgin:../z_tools/fdimg0at.tek \ wbinimg src:ipl.bin len:512 from:0 to:0 \ copy from:haribote.sys to:@: \ imgout:haribote.img
测试:打开cmd.bat,输入make img
(文件夹harib00e)
第一次见到sys文件,好奇心又上来了
用BZ打开haribote.sys文件看看
文件名称,写在0x00:2600地址以后的地方;文件内容,写在0x00:4200地址以后的地方。
之前我们规划了启动区和装载区
启动区执行的是haribote.sys内容
从启动区执行操作系统
虽然知道程序内容在磁盘映像上0x00:4200地址,但是怎么执行呢?
首先要明白,磁盘内容最终要装载到内存地址。
而对于磁盘来说,在内存中的第一个地址不是0x00:0000,而是0x00:8000。
所以我们要做一下加法运算0x00:8000+0x00:4200=0x00:c200
所以启动区内容位于内存的0x00:c200地址,缩写成0xc200
把内存地址写到nas内部
更新:haribote.nas
; haribote-os; TAB=4 ORG 0xc200 fin: HLT JMP fin
跳转到内存地址
更新:ipl.nas
next: ....此处省略一大堆代码,自行脑补,脑补不成看源文件 ;增加内容 JMP 0xc200
测试:打开cmd,输入make run
连个hello world都没有,看不出是否成功执行操作系统!
确认操作系统的执行情况
之前是黑屏白字
这次弄个图形界面
更新:haribote.nas
; haribote-os; TAB=4 ORG 0xc200 ; 程序内容的内存地址 MOV AL,0x13 ; VGA显卡,320x200 x8bit色彩 MOV AH,0x00 INT 0x10fin: HLT JMP fin
图形模式只用了三行代码!
AL,0x03:16色字符模式,80 × 25 AL,0x12:VGA 图形模式,640 × 480 × 4位彩色模式,独特的4面 存储模式 AL,0x13:VGA 图形模式,320 × 200 × 8位彩色模式,调色板模式 ( 用256种颜色 )AL,0x6a:扩展VGA 图形模式,800 × 600 × 4位彩色模式,独特的 4面存储模式(有的显卡不支持)设定AH=0x00后,调用显卡BIOS的函数,这样就可以切换显示模式了
更新:ipl.nas文件
next: .....内容自行脑补 ;增加内容 MOV [0x0ff0],CH ; 赋值,磁盘装载内容的开始地址(内存地址)0x0ff0 JMP 0xc200 ;跳到,磁盘装载内容的开始地址(内存地址)0xc200
我们知道了磁盘装载内容的开始地址(内存)是0xc200,还需要知道结束地址(内存)0x0ff0,这样启动区程序算完成。
总结一下
img 文件:用来给磁盘分区(启动区和装载区)sys 文件:操作系统内容(被启动区识别)其他文件:生成这两个文件的过渡文件
测试:打开cmd,输入make run
如果懒的写代码,运行harib00g文件夹
wuhoo~~~
成功调用图形界面!
虽然只有嘿嘿嘿
32位模式预热准备
16位优势:直接调用BIOS函数(因为BIOS是用16位机器语言写的)。
32位优势:使用更多的寄存器,但不能直接调用BIOS函数,需要变通一下。
64位优势:难度大,先放弃
看看32位中如何使用BIOS函数
修改:haribote.nas文件
; haribote-os; TAB=4; --------------------有关BOOT_INFO (information信息)CYLS EQU 0x0ff0 ; 设定启动区LEDS EQU 0x0ff1 ;LED灯泡VMODE EQU 0x0ff2 ; 关于颜色数目的信息,颜色的位数SCRNX EQU 0x0ff4 ; 分辨率的X(screen x)SCRNY EQU 0x0ff6 ; 分辨率的Y(screen y)VRAM EQU 0x0ff8 ; 图像缓冲区的开始地址;----------------------------------内容装载开始地址 ORG 0xc200 ; 内容开始地址;----------------------------------切换显卡 MOV AL,0x13 ; VGA显卡。320x200x8bit位色彩 MOV AH,0x00 INT 0x10;----------------------------------设置画面以及分辨率 MOV BYTE [VMODE],8 ; 记录画面模式 MOV WORD [SCRNX],320 ;分辨率宽320像素 MOV WORD [SCRNY],200 ;分辨率高200像素 MOV DWORD [VRAM],0xa0000 ;显卡内存,即video RAM; ------------------------------------用BIOS取得键盘上各种LED指示灯状态 MOV AH,0x02 INT 0x16 ; keyboard BIOS MOV [LEDS],AL;--------------------------------------休眠功能,省电!fin: HLT JMP fin
导入C语言
一开始学机器语言
后来又学了汇编语言
现在又学C语言
我们要把haribote.sys改名为asmhead.nas
新增了很多内容,大家不要怕!作者说了,为了用C语言,不得不写进去,以后会看懂!
; haribote-os; TAB=4BOTPAK EQU 0x00280000 DSKCAC EQU 0x00100000 DSKCAC0 EQU 0x00008000 ; 有关BOOT_INFO (information信息)CYLS EQU 0x0ff0 ; 设定启动区LEDS EQU 0x0ff1VMODE EQU 0x0ff2 ; 关于颜色数目的信息,颜色的位数SCRNX EQU 0x0ff4 ; 分辨率的X(screen x)SCRNY EQU 0x0ff6 ; 分辨率的Y(screen y)VRAM EQU 0x0ff8 ; 图像缓冲区的开始地址 ORG 0xc200 ; 这个程序将被装在到内存指定位置 MOV AL,0x13 ; VGA显卡。320x200x8bit位色彩 MOV AH,0x00 INT 0x10 MOV BYTE [VMODE],8 ; 记录画面模式 MOV WORD [SCRNX],320 MOV WORD [SCRNY],200 MOV DWORD [VRAM],0x000a0000; 用BIOS取得键盘上各种LED指示灯状态 MOV AH,0x02 INT 0x16 ; keyboard BIOS MOV [LEDS],AL; ----------------------------以下是新增内容,为了写C语言 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 pipelineflushpipelineflush: MOV AX,1*8 MOV DS,AX MOV ES,AX MOV FS,AX MOV GS,AX MOV SS,AX MOV ESI,bootpack MOV EDI,BOTPAK MOV ECX,512*1024/4 CALL memcpy MOV ESI,0x7c00 MOV EDI,DSKCAC MOV ECX,512/4 CALL memcpy MOV ESI,DSKCAC0+512 MOV EDI,DSKCAC+512 MOV ECX,0 MOV CL,BYTE [CYLS] IMUL ECX,512*18*2/4 SUB ECX,512/4 CALL memcpy MOV EBX,BOTPAK MOV ECX,[EBX+16] ADD ECX,3 SHR ECX,2 JZ skip MOV ESI,[EBX+20] ADD ESI,EBX MOV EDI,[EBX+12] CALL memcpyskip: MOV ESP,[EBX+12] JMP DWORD 2*8:0x0000001bwaitkbdout: IN AL,0x64 AND AL,0x02 JNZ waitkbdout RETmemcpy: MOV EAX,[ESI] ADD ESI,4 MOV [EDI],EAX ADD EDI,4 SUB ECX,1 JNZ memcpy RET ALIGNB 16GDT0: RESB 8 DW 0xffff,0x0000,0x9200,0x00cf DW 0xffff,0x0000,0x9a28,0x0047 DW 0GDTR0: DW 8*3-1 DD GDT0 ALIGNB 16bootpack:
下面开始就是C语言了
新建:bootpack.c文件,并添加内容(老规矩,创建txt文件,改后缀)
void HariMain(void){ fin: goto fin; }函数(功能,技能)名字叫HariMain,且不带参数(void),不返回任何值程序就是从以HariMain命名的函数开始运行的,所以这个函数名不能更改goto实际上也是被编译成JMP指令
bootpack.c是怎样变成机器语言的呢?
使用cc1.exe从bootpack.c生成bootpack.gas。使用gas2nask.exe从bootpack.gas生成bootpack.nas。使用nask.exe从bootpack.nas生成bootpack.obj。使用obi2bim.exe从bootpack.obj生成bootpack.bim。使用bim2hrb.exe从bootpack.bim生成bootpack.hrb。使用copy指令将asmhead.bin与 bootpack.hrb单纯结合到起来,就成了haribote.sys。
接下来,把上面的生成命令写到makefile文件
修改:makefile文件
TOOLPATH = ../z_tools/INCPATH = ../z_tools/haribote/MAKE = $(TOOLPATH)make.exe -rNASK = $(TOOLPATH)nask.exeCC1 = $(TOOLPATH)cc1.exe -I$(INCPATH) -Os -Wall -quietGAS2NASK = $(TOOLPATH)gas2nask.exe -aOBJ2BIM = $(TOOLPATH)obj2bim.exeBIM2HRB = $(TOOLPATH)bim2hrb.exeRULEFILE = $(TOOLPATH)haribote/haribote.rulEDIMG = $(TOOLPATH)edimg.exeIMGTOL = $(TOOLPATH)imgtol.comCOPY = copyDEL = deldefault : $(MAKE) imgipl10.bin : ipl10.nas Makefile $(NASK) ipl10.nas ipl10.bin ipl10.lstasmhead.bin : asmhead.nas Makefile $(NASK) asmhead.nas asmhead.bin asmhead.lstbootpack.gas : bootpack.c Makefile $(CC1) -o bootpack.gas bootpack.cbootpack.nas : bootpack.gas Makefile $(GAS2NASK) bootpack.gas bootpack.nasbootpack.obj : bootpack.nas Makefile $(NASK) bootpack.nas bootpack.obj bootpack.lstnaskfunc.obj : naskfunc.nas Makefile $(NASK) naskfunc.nas naskfunc.obj naskfunc.lstbootpack.bim : bootpack.obj naskfunc.obj Makefile $(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map \ bootpack.obj naskfunc.objbootpack.hrb : bootpack.bim Makefile $(BIM2HRB) bootpack.bim bootpack.hrb 0haribote.sys : asmhead.bin bootpack.hrb Makefile copy /B asmhead.bin+bootpack.hrb haribote.sysharibote.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 img : $(MAKE) haribote.imgrun : $(MAKE) img $(COPY) haribote.img ..\z_tools\qemu\fdimage0.bin $(MAKE) -C ../z_tools/qemuinstall : $(MAKE) img $(IMGTOL) w a: haribote.imgclean : -$(DEL) *.bin -$(DEL) *.lst -$(DEL) *.gas -$(DEL) *.obj -$(DEL) bootpack.nas -$(DEL) bootpack.map -$(DEL) bootpack.bim -$(DEL) bootpack.hrb -$(DEL) haribote.syssrc_only : $(MAKE) clean -$(DEL) haribote.img
这样大功告成了!
重新捋一遍文件作用(学多了,容易忘掉)
ipl10.nas:用来分区磁盘(启动区和装载区)asmhead.nas:设置bios函数等,为C语言调用提前设置bootpack.c:用来生成haribote.syscmd.bat:启用cmd窗口makefile:包含各种生成文件命令(核心文件img和sys)make.bat:一键生成所有文件,cmd都不用打开
实现HLT
最后再添加一个省电功能
新建:naskfunc.nas文件,添加以下内容(老规矩,创建txt,改后缀)
; naskfunc; TAB=4 [FORMAT "WCOFF"] ; 制作目标文件的模式[BITS 32] ; 制作32位模式用的机械语言;制作目标文件的信息[FILE "naskfunc.nas"] ; 源文件名信息 GLOBAL _io_hlt ; 程序中包含的函数名 ;以下是实际的函数[SECTION .text] ; 目标文件中写了这些之后再写程序_io_hlt: ; void io_hlt(void); HLT RET
看不懂没关系,知道干啥用就可以
我们要在c语言中添加省电功能
修改:bootpack.c
void io_hlt(void); /*告诉C编译器,有一个函数在别的文件里*/ void HariMain(void){ fin: io_hlt(); /*执行naskfunc.nas里的_io_hlt*/ goto fin;}
测试:打开cmd.bat,输入make run
(运行最后一个文件夹harib00j)
今
天
内
容
太
长
了
今天就到这里,洗洗睡了!
标签: #flacs软件教学视频 #fin c语言