今天学习了第三天的内容,相比较前两天的内容有点难,但是还好成果出来啦。本次主要的改进之处是修改了主函数的名字,是我们可以不拘泥作者的要求。
我们先看一下运行结果截图:
此图为正常的运行结果,到现在操作系统采用了汇编+C语言的方式。我们看一下操作系统的主函数:
/*告诉C编译器,有一个函数在别的文件里*/
void io_hlt(void);
void UcanMain(void)
{
fin:
io_hlt(); /*执行nashfunc.nas里的_io_hlt*/
goto fin;
}
注:原来的代码中的主函数只能为HariMain,不能修改,但是我发现在其调用的库中可以修改,故将其修改为自己想要的函数名字,需要修改下面的部分:
如果需要,需要修改haribote.rul文件上面黄色的部分,除此之外还要修改文件:
需要将harilibc.lib文件上面圈起来的部分修改为自己想要的名字,但注意大小写,大小写一定要跟源文件中的一样。
下面是函数_io_hlt所在的文件源码:
; naskfunc
; TAB=4
[FORMAT "WCOFF"]
[BITS 32]
[FILE "naskfunc.nas"]
GLOBAL _io_hlt
[SECTION .text]
_io_hlt:
HLT
RET
下面是ucan23.nas文件的源码
; ucan23-os
; TAB=4
BOTPAK EQU 0x00280000
DSKCAC EQU 0x00100000
DSKCAC0 EQU 0x00008000
; 有关BOOT_INFO
CYLS EQU 0x0ff0
LEDS EQU 0x0ff1
VMODE EQU 0x0ff2
SCRNX EQU 0x0ff4
SCRNY EQU 0x0ff6
VRAM EQU 0x0ff8
ORG 0xc200
MOV AL, 0x13
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
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
[INSTREST "i486p"]
LGDT [GDTR0]
MOV EAX,CR0
AND EAX, 0x7fffffff
OR EAX, 0x00000001
MOV CR0, EAX
JMP pipelineflush
pipelineflush:
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 memcpy
ship:
MOV ESP, [EBX+12]
JMP DWORD 2*8:0X0000001B
waitkdbout:
IN AL, 0x64
AND AL, 0x02
JNZ waitkdbout
RET
memcpy:
MOV EAX, [ESI]
ADD ESI, 4
MOV [EDI], EAX
ADD EDI, 4
SUB ECX, 1
JNZ memcpy
RET
ALIGNB 16
GDT0:
RESB 8
DW 0xffff,0x0000,0x9200,0x00cf
DW 0xffff,0x0000,0x9a28,0x0047
DW 0
GDTR0:
DW 8*3-1
DD GDT0
ALIGNB 16
bootpack:
;fin:
; HLT
; JMP fin
接下来是引导文件ucan23ipl.nas的源码:
; ucan23-os
; TAB-4
CYLS EQU 10
ORG 0x7c00 ;指明程序的装载地址
; 以下这段是标准FAT12格式软盘专用的代码
JMP entry
DB 0x90
DB "UCAN23LD" ;启动区的名称可以是任意的字符串(8字节)
DW 512 ;每个扇区的大小
DB 1 ;簇的大小
DW 1
DB 2
DW 224
DW 2880
DB 0xf0
DW 9
DW 18
DW 2
DD 0
DD 2880
DB 0,0,0x29
DD 0xffffffff
DB "UCAN23-OS "
DB "FAT12 "
RESB 18
;程序主体
entry:
MOV AX, 0 ;初始化寄存器
MOV SS, AX
MOV SP, 0x7c00
MOV DS, AX
;读磁盘
MOV AX, 0x0820
MOV ES, AX
MOV CH, 0
MOV DH, 0
MOV CL, 2
readloop:
MOV SI, 0 ;记录失败次数的寄存器
retry:
MOV AH, 0x02
MOV AL, 1
MOV BX, 0
MOV DL, 0x00
INT 0x13
JNC next
ADD SI, 1
CMP SI, 5
JAE error
MOV AH, 0x00
MOV DL, 0x00
INT 0x13
JMP retry
;JMP error
next:
MOV AX, ES
ADD AX, 0x0020
MOV ES, AX
ADD CL, 1
CMP CL, 18
JBE readloop
MOV CL, 1
ADD DH, 1
CMP DH, 2
JB readloop
MOV DH, 0
ADD DH, 1
CMP CH, CYLS
JB readloop
MOV [0x0ff0], CH
JMP 0xc200
error:
MOV SI, msg
putloop:
MOV AL, [SI]
ADD SI, 1
CMP AL, 0
JE fin
MOV AH, 0x0e
MOV BX, 15
INT 0x10
JMP putloop
fin:
HLT
JMP fin
;信息显示部分
msg:
DB 0x0a, 0x0a ;2个换行
DB "Hello, world(ucan23)"
DB 0x0a
DB "This is my first OS"
DB 0x0a
DB "Copyright GPL"
DB 0x0a
DB "Author: ucan23(Howard)"
DB 0x0a
DB "Blog:http://blog.sina.com/rjxx007"
DB 0x0a
DB "Blog:http://blog.csdn.net/ucan23"
DB 0x0a
DB 0
RESB 0x7dfe-$
DB 0x55, 0xaa
最后是Makefile文件:
TOOLPATH = ../tolset/z_tools/
INCPATH = ../tolset/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
IMGTOL = $(TOOLPATH)imgtol.com
COPY = copy
DEL = del
default:
$(MAKE) img
ucan23ipl.bin: ucan23ipl.nas Makefile
$(NASK) ucan23ipl.nas ucan23ipl.bin ucan23ipl.lst
ucan23.bin: ucan23.nas Makefile
$(NASK) ucan23.nas ucan23.bin ucan23.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 bookpack.lst
naskfunc.obj: naskfunc.nas Makefile
$(NASK) naskfunc.nas naskfunc.obj naskfunc.lst
bootpack.bim: bootpack.obj naskfunc.obj Makefile
$(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map \
bootpack.obj naskfunc.obj
bootpack.hrb: bootpack.bim Makefile
$(BIM2HRB) bootpack.bim bootpack.hrb 0
ucan23.sys: ucan23ipl.bin bootpack.hrb Makefile
copy /B ucan23ipl.bin+bootpack.hrb ucan23.sys
ucan23.img: ucan23ipl.bin ucan23.sys Makefile
$(EDIMG) imgin:../tolset/z_tools/fdimg0at.tek \
wbinimg src:ucan23ipl.bin len:512 from:0 to:0 \
copy from:ucan23.sys to:@: \
imgout:ucan23.img
asm:
$(MAKE) ucan23ipl.bin
img:
$(MAKE) ucan23.img
run:
$(MAKE) img
$(COPY) ucan23.img ..\tolset\z_tools\qemu\fdimage0.bin
$(MAKE) -C ../tolset/z_tools/qemu
install:
$(MAKE) img
$(IMGTOL) w a: ucan23.img
clean:
-$(DEL) *.bin
-$(DEL) *.lst
-$(DEL) *.gas
-$(DEL) *.obj
-$(DEL) bootpack.nas
-$(DEL) bootpack.map
-$(DEL) bootpack.bim
-$(DEL) bootpack.hrb
-$(DEL) ucan23.sys
src_only:
$(MAKE) clean
-$(DEL) ucan23.img