自制操作系统 (三) 从启动区执行操作系统并进入C世界
qq:992591601 欢迎交流
2016.04.03 2016.05.31 2016.06.29
这一章是有些复杂的,我不太懂作者为什么要把这么多内容都放进一天。
1读入了十个柱面
2从启动区执行操作系统
3进入32位
4导入C语言
makefile的内容:
TOOLPATH = ../z_tools/
INCPATH = ../z_tools/haribote/ MAKE = $(TOOLPATH)make.exe -r
NASK = $(TOOLPATH)nask.exe
NASM = $(TOOLPATH)nasm.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
IMGTOL = $(TOOLPATH)imgtol.com
COPY = copy
DEL = del default :
$(MAKE) img ipl.bin : ipl.asm Makefile
$(NASM) ipl.asm -o ipl.bin main.bin : main.nas Makefile
$(NASK) main.nas main.bin main.lst c_main.gas : c_main.c Makefile
$(CC1) -o c_main.gas c_main.c c_main.nas : c_main.gas Makefile
$(GAS2NASK) c_main.gas c_main.nas c_main.obj : c_main.nas Makefile
$(NASK) c_main.nas c_main.obj c_main.lst assemblyFunc.obj : assemblyFunc.nas Makefile
$(NASK) assemblyFunc.nas assemblyFunc.obj assemblyFunc.lst c_main.bim : c_main.obj assemblyFunc.obj Makefile
$(OBJ2BIM) @$(RULEFILE) out:c_main.bim stack:3136k map:c_main.map \
c_main.obj assemblyFunc.obj
# 3MB+64KB=3136KB c_main.hrb : c_main.bim Makefile
$(BIM2HRB) c_main.bim c_main.hrb haribote.sys : main.bin c_main.hrb Makefile
copy /B main.bin+c_main.hrb haribote.sys haribote.img : ipl.bin haribote.sys Makefile
$(EDIMG) imgin:../z_tools/fdimg0at.tek \
wbinimg src:ipl.bin len: from: to: \
copy from:haribote.sys to:@: \
imgout:haribote.img img :
$(MAKE) haribote.img run :
$(MAKE) img
$(COPY) haribote.img ..\z_tools\qemu\fdimage0.bin
$(MAKE) -C ../z_tools/qemu install :
$(MAKE) img
$(IMGTOL) w a: haribote.img clean :
-$(DEL) *.bin
-$(DEL) *.lst
-$(DEL) *.gas
-$(DEL) *.obj
-$(DEL) c_main.nas
-$(DEL) c_main.map
-$(DEL) c_main.bim
-$(DEL) c_main.hrb
-$(DEL) haribote.sys src_only :
$(MAKE) clean
-$(DEL) haribote.img
注意end.exe,在第二天,作者提到:自己开发的磁盘映像管理工具end.exe,先读入一个空白的磁盘映像文件,然后在开头写入ipl.bin的内容,最后将结果输出为名为helloos.img的磁盘映像文件。
这样一来,逻辑上就很简单了,用makefile,调用end.exe,将ipl10.nas和操作系统代码,制成一个img文件。ipl10.nas是启动区。最后操作系统的启动是,在启动区启动。
然后我们用工具观察制成的img,会发现:
作者得出的结论:
一般向一个空软盘保存文件时
(1)文件名会写在0x002600以后的地方;
(2)文件内容会写在0x004200以后的地方。
所以,要执行磁盘映像上位于0x004200号地址的程序,现在的程序是从启动区开始,把磁盘上的内容装载到内存0x8000号地址,所以磁盘0x4200处的内容就应该位于内存0x8000+0x4200=0xc200号地址。
所以从启动区,启动操作系统就只需要jmp到0xc200地址即可。
这两张图可以简单解释原理(第二张是我画的):
ipl.asm:
; author: 无 名
; date: 2016.05.31 06.01 06.02 06.03
; description: bootsector CYLS equ
org 07c00h ;以下,FAT12格式引导程序专用代码
JMP entry
DB 0x90
DB "HELLOIPL" ; name
DW ; size of a sector(must be 512byte)
DB ; size of a cluster(must be a sector)
DW ; FAT begin from 1st sector
DB ; FAT num
DW ; size of root directory
DW ; size of disk(2880 sectors)
DB 0xf0 ; type of disk
DW ; length of FAT(must be 9 sectors)
DW ; how many sectors with a track
DW ; head num
DD ; 不使用分区
DD ; size of disk(2880 sectors)
DB ,,0x29
DD 0xffffffff
DB "HELLO-OS "
DB "FAT12 "
RESB ; 先空出18字节 entry:
mov ax,
mov ss,ax
mov sp,0x7c00
mov ds,ax ;read disk mov ax,0x0820
mov es,ax
mov ch, ;柱面0
mov dh, ;磁头0
mov cl, ;扇区2 readloop:
mov si, ;记录失败次数 retry:
mov ah,0x02 ;ah=0x02:读入磁盘
mov al, ;a sector
mov bx,
mov dl,0x00 ;A驱动器
int 0x13 ;调用磁盘bios
jnc next ;没出错跳转next
add si,
cmp si, ;if si > 5 errorへ
jae error
mov ah,0x00
mov dl,0x00
int 0x13 ;重置驱动器
jmp retry next:
mov ax,es
add ax,0x0020
mov es,ax
add cl,
cmp cl,
jbe readloop ; if cl <= 18 readloopへ
mov cl,
add dh,
cmp dh,
jb readloop ; if dh < 2 readloopへ
mov dh,
add ch,
cmp ch,CYLS
jb readloop ; if ch < CYLS readloopへ ;mov ax,cs ; print boot poem
;mov ds,ax
;mov es,ax
;call PrintStr
;jmp $ mov [0x0ff0],ch
jmp 0xc200 fin:
hlt
jmp fin error:
mov si,msg putloop:
mov al,[si]
add si,
cmp al, ; if al == 0 finへ
je fin
mov ah,0x0e
mov bx,
int 0x10
jmp putloop PrintStr:
mov ax,BootPoem ; print boot poem
mov bp,ax
mov cx,
mov ax,01301h
mov bx,00009h
mov dh,
mov dl,
int 10h
ret msg:
db 0x0a, 0x0a
db "load error"
db 0x0a
db BootPoem:
db "Hold fast to dreams"
db 0x0a
db "For if dreams die"
db 0x0a
db "Life is a broken-winged bird "
db 0x0a
db "That can never fly"
db 0x0a
db "Hold fast to dreams"
db 0x0a
db "For when dreams go"
db 0x0a
db "Life is a barren field"
db 0x0a
db "Frozen only with snow"
db 0x0a times -($-$$) db ; 接下来510字节写0
dw 0xaa55 ; 最后一个字0xaa55是引导程序结束标志
main.nas
; sonn-os boot asm
; TAB=4
; author: 无 名
; date: 2016.06.03 2016.06.05
; description: jmp to 32bit BOTPAK EQU 0x00280000
DSKCAC EQU 0x00100000
DSKCAC0 EQU 0x00008000 ; BOOT_INFO 数据结构
CYLS EQU 0x0ff0 ; 启动区
LEDS EQU 0x0ff1
VMODE EQU 0x0ff2 ; 颜色数目的信息。颜色的位数
SCRNX EQU 0x0ff4 ; 分辨率的X
SCRNY EQU 0x0ff6 ; 分辨率的Y
VRAM EQU 0x0ff8 ; 图像缓冲区的开始地址 ORG 0xc200 ; 这个程序要被装载到内存什么地方 ; 画面模式定位 MOV AL,0x13 ; VGA显卡,320*200*8位彩色
MOV AH,0x00
INT 0x10
MOV BYTE [VMODE], ; 记录画面模式
MOV WORD [SCRNX],
MOV WORD [SCRNY],
MOV DWORD [VRAM],0x000a0000 ; 用BIOS取得键盘上各种LED指示灯的状态 MOV AH,0x02
INT 0x16 ; keyboard BIOS
MOV [LEDS],AL ; PIC关闭一切中断
; 根据AT兼容机的规格、初始化PIC
; 必须在CLI之前进行,到CLI挂起
; 随后进行PIC初始化 MOV AL,0xff
OUT 0x21,AL
NOP ; 如果连续进行OUT命令,有些机种不可以
OUT 0xa1,AL CLI ; 禁止CPU级别中断 ; OPEN A20GATE CALL waitkbdout
MOV AL,0xd1
OUT 0x64,AL
CALL waitkbdout
MOV AL,0xdf ; enable A20
OUT 0x60,AL
CALL waitkbdout ; 保护模式 [INSTRSET "i486p"] ; 开始使用486命令 LGDT [GDTR0] ; 临时GDT
MOV EAX,CR0
AND EAX,0x7fffffff ; bit31设0,禁止分页
OR EAX,0x00000001 ; bit0设1,为了切换到保护模式
MOV CR0,EAX
JMP pipelineflush
pipelineflush:
MOV AX,* ; 可读写的段,32bit
MOV DS,AX
MOV ES,AX
MOV FS,AX
MOV GS,AX
MOV SS,AX ; 转移 MOV ESI,c_main
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 ; main到此为止接下来是c_main ; c_main启动 MOV EBX,BOTPAK
MOV ECX,[EBX+]
ADD ECX, ; ECX += 3;
SHR ECX, ; ECX /= 4;
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
c_main:
这里前一部分是对32位模式的启动,后一部分是对C语言的准备。
其实不是很好理解,等我理解了再回来补充吧。
。。EQU。。这样的语句其实就相当于C语言中的#define语句。
mov dword[vram],0x000a0000;
vram,显卡内存,也就是用于显示画面的内存,将之存储0xa0000,也就是种对画面的设置了。具体暂时不讨论。
这段代码应该还涉及16位进入32位,GDT寻址等等,这么重要的东西,作者都没有讲。无语。
c_main.c:
void io_hlt(void); void HariMain(void)
{ fin:
io_hlt();
goto fin; }
c_main.c调用的汇编函数在assemblyFunc.nas中,这需要一个编译(将C语言编译为汇编文件c_main.nas)、链接(两个.nas汇编文件)的过程
_io_hlt: ; void io_hlt(void);
HLT
RET
自制操作系统 (三) 从启动区执行操作系统并进入C世界的更多相关文章
- Linux操作系统之更改启动菜单的背景图实战案例
Linux操作系统之更改启动菜单的背景图实战案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.制作图像并上传到服务器 1>.使用window 10操作系统自带的画图工具 ...
- VMware12提示 已将该虚拟机配置为使用 64 位客户机操作系统。但是,无法执行 64 位操作。
VMware12提示 已将该虚拟机配置为使用 64 位客户机操作系统.但是,无法执行 64 位操作. 此主机支持 Intel VT-x,但 Intel VT-x 处于禁用状态 解决办法: 下载LeoM ...
- vmware 已将该虚拟机配置为使用 64 位客户机操作系统。但是,无法执行 64 位操作。
错误提示:已将该虚拟机配置为使用 64 位客户机操作系统.但是,无法执行 64 位操作. 此主机支持 Intel VT-x,但 Intel VT-x 处于禁用状态. 如果已在 BIOS/固件设置中禁用 ...
- mysql数据库,如何在登录mysql之后执行操作系统上的SQL脚本?
需求描述: 通过mysql客户端登录到mysql数据库,如何执行操作系统上的SQL脚本文件呢? 操作过程: 1.编写测试脚本文件 [mysql@redhat6 scripts]$ cat SeCoun ...
- FreeNOS学习2——操作系统是如何启动的
The System Boot Process Explained:https://www.webopedia.com/DidYouKnow/Hardware_Software/BootProcess ...
- spring-boot的三种启动方式[z]
https://blog.csdn.net/u011425751/article/details/79507386 有段时间没有写博客了,也在努力的从传统单机开发向分布式系统过度,所以再次做一些笔记, ...
- Spring Boot干货系列:(三)启动原理解析
Spring Boot干货系列:(三)启动原理解析 2017-03-13 嘟嘟MD 嘟爷java超神学堂 前言 前面几章我们见识了SpringBoot为我们做的自动配置,确实方便快捷,但是对于新手来说 ...
- 《转》深入理解Activity启动流程(三)–Activity启动的详细流程2
本文原创作者:Cloud Chou. 出处:本文链接 本系列博客将详细阐述Activity的启动流程,这些博客基于Cm 10.1源码研究. 深入理解Activity启动流程(一)--Activity启 ...
- 《转》深入理解Activity启动流程(三)–Activity启动的详细流程1
本文原创作者:Cloud Chou. 出处:本文链接 本系列博客将详细阐述Activity的启动流程,这些博客基于Cm 10.1源码研究. 深入理解Activity启动流程(一)--Activity启 ...
随机推荐
- iOS emoji表情转码 或者判断
如果项目中有评论或者信息恢复的地方,往往会用到emoji,有时候如后台不支持emoji,就会显示乱码错误,我们可以把emoji转成unicode编码或者utf8编码格式传给服务器.当然如果后台服务器接 ...
- Html/Css(新手入门第三篇)
一.学习心得---参考优秀的网页来学习. 1我们只做的静态网页主要用的技术?html+css 只要网上看到的,他的源代码公开的.[1].先去分析,他们页面是如何布局(结构化)[2].再试着去做一下,- ...
- Java 第17章 继承
继承的概念 继承机制是面向对象程序设计不可缺少的关键概念,是实现软件可重用的根基, 是提高软件系统的可扩展性与可维护性的主要途径. 所谓继承是指一个类的定义可以基于另外一个已经存在的类,即子类基于父类 ...
- hadoop搭建初步总结
1.安装JDK1.1上传运用软件FileZilla,将windows上的jdk压缩包放到linux的root目录下 1.2解压jdk #创建文件夹 mkdir /usr/java(不要挂在在" ...
- sql如何做递归层次查询
DROP FUNCTION IF EXISTS `WhlFucGetIDsOnID`; CREATE DEFINER = `root`@`127.0.0.1` FUNCTION `WhlFucGetI ...
- RabbitMQ 记录
RabbitMQ 中文文档 : http://rabbitmq.mr-ping.com/description.html 官方教程译文: 一 http://blog.csdn.net/xiaoxian ...
- <c:if>标签的使用-流程控制标签
<c:if>标签必须要有test属性,${ }表达式为ture,则执行body内容;否则不执行. 原始代码: <c:if test="${all == 1}"&g ...
- 百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换(JS版代码)
/** * Created by Wandergis on 2015/7/8. * 提供了百度坐标(BD09).国测局坐标(火星坐标,GCJ02).和WGS84坐标系之间的转换 */ //定义一些常量 ...
- UI拼图导出脚本,兼容cegui的ImageSet格式
该脚本用于photoshop,美术可以先用photoshop拼接图片,在加载该脚本导出xml格式的文件,该文件记录了每个小的图片坐标信息 // Copyright 2002-2003. Adobe S ...
- dom4j解析xml的增加信息
想要在xml中增加信息,那么就要先找到你要加信息的节点 前三行是固定模式,主要是找到xml文件的地址,并且得到根节点,再从根节点中便利出来movie的所有节点之后用集合接收 SAXReader rea ...