加入中断试试看
一直都没有考虑中断
,
现在在保护模式下把中断加上去看看是怎么回事
现在的文件有
:
kernel.asm
fatboot.asm
pnt.asm
readdisk.asm
system.asm
kernel.ld
build.bat
start.txt
start.bat
文件KERNEL.asm
; ==================================
;;
文件
: KERNEL.asm
;;
作用
:
系统在进入保护模式之前
;;
要进行的初始化操作包括
:
; 1.
载入
32
位系统文件
system.img
; 2.
设置
GDT
和中断
(
空的
)
在
32
位的时候再设置
;;
创建日期
:2006/04/30 flyback
;;
修改日期
:2006/05/07 flyback
;; http://blog.csdn.net/flyback
; ==================================
global start
extern _pntchr
extern _cls
extern _NextLine
extern _readsystem
[section .text]
[bits 16]
start:
mov ax, cs
mov ds, ax
mov ss, ax
mov sp, 0xfff0
sti
call _cls
lea si, [dword KernelLoad]
call _pntchr
call _NextLine
lea si, [dword welcomemsg]
call _pntchr
call _NextLine
call _readsystem
;
打开
A20
in al, 92h
or al, 00000010b
out 92h, al
; end
打开
A20
;
设置
GDT
cli
lea si, [dword gdtr]
lgdt [si]
; end
设置
GDT
;
设置
idt
lea si, [dword idtr]
lidt [si]
; end
设置
idt
mov eax, cr0
or eax,1
mov cr0, eax
jmp dword codesel:SYSSEG * 0x10 + SYSOFF
[bits 32]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
设置中断
0
;
显示
20
在屏幕上
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
int0x0:
pusha
mov ax,datasel
mov gs,ax
mov byte[gs:dword 0xB8000],'2'
mov byte [gs:dword 0xB8002],'0'
popa
iret
int0x1:
; =======
;
清屏幕
; =======
pusha
mov ax, datasel
mov ds, ax
mov es, ax
mov eax, dword 0xb8000
mov edi, eax
mov ecx, 25 * 80
mov ah, 0x7
mov al, ' '
rep stosw
popa
iret
[bits 16]
gdtr :
dw gdtend - gdt - 1 ; gdt
的长度
dd gdt ; gdt
的物理地址
gdt:
gdt0:
dw 0,0,0,0 ;
据说是一定要为
0
否则会有错
codesel_gdt:
dw 0xffff ;
界限
Limit
值
= 0x100000 * 0x1000 = 4GB
dw 0 ;
基地址
= 0
dw 0x9A00 ;
表示代码段
可读可执行
dw 0x00CF ;
粒度(不知道是什么意思)
datasel_gdt:
dw 0xffff ; 4GB
dw 0x0 ;
基地址
dw 0x9200 ;
数据段
可读可写
dw 0x00CF ;
粒度
gdtend:
codesel equ codesel_gdt - gdt
datasel equ datasel_gdt - gdt
align 4
idtr: dw idt_end - idt - 1 ; IDT limit
dd idt ; linear, physical address of IDT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; interrupt descriptor table (IDT)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
idt:
dw int0x0 - $$ ;
这里是
offset
dw codesel
db 0
db 0x8E
dw SYSSEG / 0x1000 ;
这里为
0x9000 / 0x1000 = 0x9
如果程序用到
int 0x0
的时候则跳转到
8:0x9:int0x0
dw int0x1 - $$
dw codesel
db 0
db 0x8E
dw SYSSEG / 0x1000
idt_end:
segment .data
welcomemsg db 'Welcome to DIY OS!'
CopyRight db ' Create by http://blog.csdn.net/flyback.',0
KernelLoad db 'KERNEL.img was loaded!',0
SYSSEG equ 0x9000
SYSOFF equ 0x1000
文件fatboot.asm
;;
文件
:fatboot.asm
;;
作用
:
从
7c00h
处启动
;;
把
kernel.img
载入到
0x90000
的地方
;;
用
32
位方式执行
;;
有文件系统
,1.44M 512bits/80sec
软盘启动,
;;
创建日期
:2004/01/30 flyback
;;
修改日期
:2006/04/24 flyback
;; http://blog.csdn.net/flyback
;; ===================================
%define loadpoint 0x9000 ;
载入点,初始化程序载入到
9000h
的地方
%define loadoffset 0x0
bits 16
ORG 0x7c00 ;
启动入口地址
main:
jmp short start ;
跳转到开始程序入口
nop ;
;
引导区文件系统数据
;----------------------------------------------------------------------------
brOEM DB ' -My-0S.' ; 0003h -
引导程序的名字
brBPS DW 0x200 ; 000Bh -
每扇区的字节数
512
brSPC DB 0x01 ; 000Dh -
每簇扇区数
brResCount DW 0x0001 ; 000Eh -
保留扇区数
brFATs DB 0x02 ; 0010h - FAT
备份数
brRootEntries DW 0x00e0 ; 0011h -
根目录入口数
brSectorCount
DW 2880 ; 0013h -
磁盘容量扇区数
< 32MB
brMedia DB 240 ; 0015h -
媒体描述符
brSPF DW 9 ; 0016h -
每
FAT
扇区数
brSPH DW 18 ; 0018h -
每磁道扇区数
brHPC DW 2 ; 001Ah -
盘面数
brHidden DD 0 ; 001Ch -
隐藏扇区数
brSectors DD 0 ; 0020h -
如果大于
32m
的扇区总数
DB 0 ; 0024h -
物理驱动器号
DB 0 ; 0025h -
系统保留
DB 29H ; 0026h -
扩展扇区标记(包含
29h
)
brSerialNum DD 00000006H ; 0027h -
卷
ID
brLabel DB 'teachosdisk' ; 002Bh -
卷标
brFSID DB 'FAT12 ' ; 0036h -
系统保留
;------------------------------------------------------------------------
start:
cli ;
关中断,防止意外中断打断程序执行
mov ax, cs ;
mov ds, ax ;
设置数据段
mov es, ax ;
mov ax, 0x0000;
设置堆栈段
mov ss, ax
mov sp, 0ffffh ;
堆栈入口
sti ;
开中断
mov si, loadmsg ;
调用显示载入信息
call pntchr
;
把磁盘目录信息载入到
7c00:0200
的地方
loadroot:
mov cx, 0
mov dx, 0
mov ax, 0x0020 ; 32
个字节
/
文件
mul WORD [brRootEntries] ; 32*224
(文件数)
= 7168
(最多所有文件所占的字节数)
div WORD [brBPS] ; 7168/512 = 14 (Root dir)
文件的目录描述字节占用的扇区数
14
xchg ax, cx ; CX = 14
mov al, [brFATs] ; 2
mul word [brSPF] ; 9 * 2 = 18
add ax, word [brResCount] ; 18 + 1 now AX = 19
mov WORD[datasector], ax ;
目录起始的扇区
19
add WORD[datasector], cx ;
数据区起始扇区
33
;
目录放入
0x0200
内存
mov bx, 0x0200
call ReadSec
;
比较目录中是否有
init.img
文件存在
mov cx, WORD [brRootEntries] ; CX:224
在目录的所有文件中寻找
mov di, 0x0200 ;
从目录入口处开始
0x200
.LOOP:
push cx ;
保护
CX = 224
mov cx, kernellen ; 8
个文件名称和
3
个扩展名称
lea si, [kernelname] ;
push di
repe cmpsb ; stop compare if cx >0 or the
; first unequal is met(zf=1)!
pop di
je loadfiledec ;if zf = 1, jmp LOAD_FAT!(Seek OK!)
pop cx
add di, 0x0020 ;
跳到下一个目录入口
loop .LOOP ; cx
自动减
jmp failure
;
载入文件描述子节
loadfiledec:
;
把启动的镜像文件
*.img
文件的起始单元保存起来
mov si, CRLF
call pntchr
mov si, loadfat
call pntchr
lea si, [kernelname]
call pntchr
mov dx, WORD [di + 0x001A] ;the file's first cluster
mov WORD [cluster], dx ; store the first cluster
;
计算
fat
的大小并保存到
07c00:0x0200(ds:bx)
xor ax, ax
mov al, BYTE [brFATs] ; al:2
mul WORD [brSPF] ; AH:18 = 9*2
mov cx, ax ; CX:18
;
读取数据放入到
0x7c00:0x0200 ds:bx
mov ax, WORD [brResCount] ; AX:1
mov bx, 0x0200 ;
call ReadSec ; AX:1 CX:18 BX:0200
;
读取
img
放入
9000:0x0000
处
mov ax, loadpoint
mov es, ax
mov bx, loadoffset
push bx
LOAD_IMAGE:
mov ax, WORD [cluster] ; cluster to read
pop bx ; buffer to read into
call ClusterLBA ; convert cluster to LBA
; AX:[cluster] ES:BX[9000:0000](dest)
xor cx, cx
mov cl, BYTE [brSPC] ; CL:1
call ReadSec ; AX:LBA CX:1 BX:0000 ES:0100
push bx
;
计算下一个单元
mov ax, WORD [cluster] ; identify current cluster
mov cx, ax ; copy current cluster
mov dx, ax ; copy current cluster
shr dx, 0x0001 ; divide by two
add cx, dx ; sum for (3/2)
mov bx, 0x200 ; location of FAT in memory
add bx, cx ; index into FAT
mov dx, WORD [bx] ; read two bytes from FAT
test ax, 0x0001
jnz .ODD_CLUSTER
.EVEN_CLUSTER:
and dx, 0000111111111111b ; take low twelve bits
jmp .DONE
.ODD_CLUSTER:
shr dx, 0x0004 ; take high twelve bits
.DONE:
mov WORD [cluster], dx ; store new cluster
cmp dx, 0x0FF0 ; test for end of file,>=0x0FF0: end or bad!
jb LOAD_IMAGE ; if dx<0x0ff0 (CF=1), jmp Load_image
DONE: ; this Label is not used!
jmp gotopm
failure:
mov si, CRLF
call pntchr
mov si, loadfail
call pntchr
hlt
; ----------------
子程序区
-------------------------
;*********************
显示字符串
********************************************
;
;
;
;***************************************************************************
pntchr:
pusha
.pnt:
lodsb ;
从
DS:SI
装载一个字符到
AL
or al,al ;
jz endpntchr ;
如果
al = 0,
返回
;
mov ah,0x0E ;
mov bx,0x004a ;
int 0x10 ;
调用
bios
中断显示字符
jmp .pnt ;
;
endpntchr: ;
popa
ret ;
返回
;*************************************************************************
; PROCEDURE ReadSec
;
从
ax+1
的地方把
cx
个扇区载入到
es:bx
的内存
;
注意扇区是从
2
开始,
1
扇区已经读入了
;*************************************************************************
ReadSec:
.Main:
.secloop:
push ax
push bx
push cx ;protect ax, bx, cx
call LBACHS ;
调用转换
mov ah, 0x02 ; BIOS
读取扇区命令
mov al, 0x01 ;
一个扇区
mov ch, BYTE [Track] ; track
mov cl, BYTE [Sector] ; sector
mov dh, BYTE [Head] ; head
mov dl, 0 ;
因为是
a:
所以为
0
int 0x13 ;
调用中断
jnc .SUCCESS ; test for read error
xor ax, ax
pop cx
pop bx
pop ax
jnz .secloop
jmp failure ;
错误则显示出错信息并停止
hlt
.SUCCESS
mov si, Progress
call pntchr
pop cx
pop bx
pop ax
add bx, WORD [brBPS] ;
读取下一个扇区的内容
inc ax
loop .Main ; cx -= 1, if cx != 0, jmp .main
ret
;*************************************************************************
; PROCEDURE LBACHS
;
转换逻辑块访问为读取磁盘所使用的磁道,盘面,扇区
;
相对扇区
= (
逻辑扇区
/
每磁道扇区数
) + 1
;
相对盘面
= (
逻辑扇区
/
每磁道扇区数
) MOD
盘面数
;
相对磁道
=
逻辑扇区
/ (
每磁道扇区数
*
盘面数
)
;*************************************************************************
LBACHS:
xor dx, dx ; dx = 0
div WORD [brSPH] ; div m16: ax/18 ->
商
:ax
余数
:dx
inc dl ;
mov BYTE [Sector], dl ;sector No relative to the Track
xor dx, dx ; dx = 0
div WORD [brHPC] ; ax/2 ->
商
:ax
余数
:dx
mov BYTE [Head], dl ;
mov BYTE [Track], al ;
ret
;*************************************************************************
; PROCEDURE ClusterLBA
;
转换单元访问到直接扇区访问
; LBA = (cluster - 2) * sectors per cluster
;*************************************************************************
ClusterLBA:
sub ax, 0x0002 ; zero base cluster number
xor cx, cx
mov cl, BYTE [brSPC] ; convert byte to word
mul cx
add ax, WORD [datasector] ; base data sector
ret
;--------------------
数据区
-------------------------------
loadmsg db 'Boot',0 ;
要显示的字符窜以
0
结尾
loadfail db 'Load Fail',0 ;
载入失败信息
Sector db 0x00
Head db 0x00
Track db 0x00
datasector dw 0x0000 ; 33
数据区起始扇区号
rootaccess equ 0x0200 ;
存放目录数据的偏移地址
cluster dw 0x0000
CRLF db 13,10,0
Progress db ".", 0
loadfat db 'Load', 0 ;
字符串,回车,换行,
0
kernelname db "KERNEL IMG" ; 11 chars
kernellen equ $ - kernelname ;
长度
gdtr :
dw gdtend - gdt - 1 ; gdt
的长度
dd gdt ; gdt
的物理地址
gdt:
gdt0:
dw 0,0,0,0 ;
据说是一定要为
0
否则会有错
codesel_gdt:
dw 0xffff ;
界限
Limit
值
= 0x100000 * 0x1000 = 4GB
dw 0 ;
基地址
= 0
dw 0x9A00 ;
表示代码段
可读可执行
dw 0x00CF ;
粒度(不知道是什么意思)
datasel_gdt:
dw 0xffff ; 4GB
dw 0x0 ;
基地址
dw 0x9200 ;
数据段
可读可写
dw 0x00CF ;
粒度
gdtend:
codesel equ codesel_gdt - gdt
datasel equ datasel_gdt - gdt
;
从这里启动
KERNEL,
原来要作为保护模式的跳转
gotopm:
jmp dword loadpoint:loadoffset
; -----------------------------------------------------------------
times 510 - ($ - $$) db 0 ;
保证
boot
区有
512
个字节
dw 0AA55h ; boot
区标记
times 1474560 - ( $ - $$) db 0 ;
大小为
1.44M
文件 pnt.asm
; ==================================
;;
文件
: pnt.asm
;;
作用
:
需要调用的显示部分子程序
;;
创建日期
:2006/04/30 flyback
;;
修改日期
:2006/05/07 flyback
;; http://blog.csdn.net/flyback
;;
fly-back@163.com
; ==================================
[bits 16]
[global _pntchr]
[global _cls]
[global _NextLine]
[global _Num2Str]
[global _ShowAddress]
[global _NextCursor]
segment .data
_row dw 0
_col dw 0
[section .text]
_pntchr:
push ebx
push eax
push si
push di
push cx
push es
mov ax, 0xb800
mov es, ax
push si
lea si, [dword _row]
mov ax, [si]
mov bx, 80 * 2
mul bx
lea si, [dword _col]
add ax, [si]
mov di, ax
pop si
.pnt:
mov al, byte[ds:si]
test al, 0xff
jz .endpntchr
mov byte[es:di], al
inc di
mov byte[es:di], 0x7
inc di
inc si
call _NextCursor
jmp .pnt ;
.endpntchr: ;
pop es
pop cx
pop di
pop si
pop eax
pop ebx
ret ;
返回
; =======
;
清屏幕
; =======
_cls:
push ax
push es
push di
push ecx
push si
; push fs
mov ax, 0xb800
mov es, ax
mov ax, 0
mov di, ax
mov ecx, 25 * 80
mov ah, 0x7
mov al, ' '
rep stosw
mov ax, 0
mov es, ax
lea si, [dword _row]
mov [si], ax
lea si, [dword _col]
mov [si], ax
; pop fs
pop si
pop ecx
pop di
pop es
pop ax
ret
; =============
;
跳到下一行
; =============
_NextLine:
push si
lea si, [dword _row]
inc word[si]
lea si, [dword _col]
mov word [si], 0
pop si
ret
; =================
;
设置光标的下一个位置
; =================
_NextCursor:
push si
lea si, [dword _col]
inc word[si]
inc word[si]
cmp word [si], 80 * 2
jne .addcol
mov word [si], 0
lea si, [dword _row]
inc word[si]
.addcol:
pop si
ret
; ===================
;
显示指定位置的地址内容
;
入口参数
:
; si =
有效地址
; cx =
内容个数
; ===================
_ShowAddress:
push eax
.lod
lodsb
or cx,cx
jz .end
push si
call _Num2Str
call _pntchr
; call _NextLine
pop si
loop .lod
.end
pop eax
ret
; ===========
;
把
al
的数按
16
;
进制显示出来
; al = num
; ===========
_Num2Str:
push bx
push eax
jmp .handle
.show db ' '
.dath db 0
.datl db 0,0
.tab db '0123456789ABCDEF'
.handle:
and ax, 0xff
push ax
and ax, 0x0f
lea si, [dword .tab]
add si, ax
mov al, byte[si]
lea si, [dword .datl]
mov [si], al
pop ax
shr ax, 4
and ax, 0x0f
lea si, [dword .tab]
add si, ax
mov al, byte[si]
lea si, [dword .dath]
mov [si], al
lea si, [dword .show]
pop eax
pop bx
ret
文件readdisk.asm
; ==================================
;;
文件
: readdisk.asm
;;
作用
:
需要调用的读读磁盘文件子程序
;;
创建日期
:2006/04/30 flyback
;;
修改日期
:2006/05/07 flyback
;; http://blog.csdn.net/flyback
;;
fly-back@163.com
; ==================================
[bits 16]
[extern _pntchr]
[extern _cls]
[extern _NextLine]
[extern _Num2Str]
[extern _ShowAddress]
[global _readsystem]
segment .data
align 4
progress db '.', 0
Load db ' Loading system file now, please wait', 0
ErrorMsg db ' An error occur!',0
SystemFileName db 'SYSTEM IMG'
SystemFileNameLen equ $ - SystemFileName
protectmode db ' Goto protected mode',0
LoadRootMsg db ' Loading root',0
LoadFileDescriptor db ' Loading file descriptor',0
LoadSystemImage db ' Loading system file image',0
NotFound db ' File not found!', 0
bpsadd equ 0xb ;brBPS DW 0x200 ; 000Bh -
每扇区的字节数
512
spcadd equ 0xd ;brSPC DB 0x01 ; 000Dh -
每簇扇区数
rescountadd equ 0xe ;brResCount DW 0x0001 ; 000Eh -
保留扇区数
fatsadd equ 0x10 ;brFATs DB 0x02 ; 0010h - FAT
备份数
rootentriesadd equ 0x11 ;brRootEntries DW 0x00e0 ; 0011h -
根目录入口数
sectorscountadd equ 0x13 ;brSectorCount DW 2880 ; 0013h -
磁盘容量扇区数
< 32MB
mediaadd equ 0x15 ;brMedia DB 240 ; 0015h -
媒体描述符
spfadd equ 0x16 ;brSPF DW 9 ; 0016h -
每
FAT
扇区数
sphadd equ 0x18 ;brSPH DW 18 ; 0018h -
每磁道扇区数
hpcadd equ 0x1a ;brHPC DW 2 ; 001Ah -
盘面数
hideadd equ 0x1c ;brHidden DD 0 ; 001Ch -
隐藏扇区数
sectors equ 0x20 ;brSectors DD 0 ; 0020h -
如果大于
32m
的扇区总数
;DB 0 ; 0024h -
物理驱动器号
;DB 0 ; 0025h -
系统保留
;DB 29H ; 0026h -
扩展扇区标记(包含
29h
)
;brSerialNum DD 00000006H ; 0027h -
卷
ID
;brLabel DB 'teachosdisk' ; 002Bh -
卷标
;brFSID DB 'FAT12 ' ; 0036h -
系统保留
SYSSEG equ 0x9000
SYSOFF equ 0x1000
Sector db 0x00
Head db 0x00
Track db 0x00
datasector dw 0x0000 ; 33
数据区起始扇区号
cluster dw 0x0000
segment .text
;*************************************************************************
; PROCEDURE ReadSec
;
从
ax+1
的地方把
cx
个扇区载入到
es:bx
的内存
;
注意扇区是从
2
开始,
1
扇区已经读入了
;*************************************************************************
ReadSec:
.Main:
.secloop:
push ax
push bx
push cx ;protect ax, bx, cx
call LBACHS ;
调用转换
mov ah, 0x02 ; BIOS
读取扇区命令
mov al, 0x01 ;
一个扇区
lea si, [dword Track]
mov ch, [si] ; track
lea si, [dword Sector]
mov cl, [si] ; sector
lea si, [dword Head]
mov dh, [si] ; head
mov dl, 0 ;
因为是
a:
所以为
0
int 0x13 ;
调用中断
jnc .SUCCESS ; test for read error
xor ax, ax
pop cx
pop bx
pop ax
jnz near .secloop
jmp failure ;
错误则显示出错信息并停止
.SUCCESS
lea si,[dword progress]
call _pntchr
pop cx
pop bx
pop ax
add bx, [fs:bpsadd] ;
读取下一个扇区的内容
inc ax
loop .gotomain ; cx -= 1, if cx != 0, jmp .main
ret
;
到
.Main
已经不能用普通跳转了
;
因为
loop
只能是
short jmp
.gotomain:
jmp near .Main
;*************************************************************************
; PROCEDURE LBACHS
;
转换逻辑块访问为读取磁盘所使用的磁道,盘面,扇区
;
相对扇区
= (
逻辑扇区
/
每磁道扇区数
) + 1
;
相对盘面
= (
逻辑扇区
/
每磁道扇区数
) MOD
盘面数
;
相对磁道
=
逻辑扇区
/ (
每磁道扇区数
*
盘面数
)
;*************************************************************************
LBACHS:
xor dx, dx ; dx = 0
div WORD [fs:sphadd] ; div m16: ax/18 ->
商
:ax
余数
:dx
inc dl ;
lea si,[dword Sector]
mov [si], dl ; sector No relative to the Track
xor dx, dx ; dx = 0
div word [fs:hpcadd] ; ax/2 ->
商
:ax
余数
:dx
lea si, [dword Head]
mov [si], dl ;
lea si, [dword Track]
mov [si], al ;
ret
;*************************************************************************
; PROCEDURE ClusterLBA
;
转换单元访问到直接扇区访问
; LBA = (cluster - 2) * sectors per cluster
;*************************************************************************
ClusterLBA:
sub ax, 0x0002 ; zero base cluster number
xor cx, cx
mov cl, BYTE [fs:spcadd] ; convert byte to word
mul cx
lea si, [dword datasector]
add ax, [si] ; base data sector
ret
_readsystem:
lea si, [dword Load]
call _pntchr
mov ax, 0x7c0
mov fs, ax
mov es, ax
loadroot:
call _NextLine
lea si, [dword LoadRootMsg]
call _pntchr
mov cx, 0
mov dx, 0
mov ax, 0x0020 ; 32
个字节
/
文件
; mul WORD [brRootEntries] ; 32*224
(文件数)
= 7168
(最多所有文件所占的字节数)
mul word [fs:rootentriesadd]
; div WORD [brBPS] ; 7168/512 = 14 (Root dir)
文件的目录描述字节占用的扇区数
14
div word [fs:bpsadd]
xchg ax, cx ; CX = 14
; mov al, [brFATs] ; 2
mov al, [fs:fatsadd]
; mul word [brSPF] ; 9 * 2 = 18
mul word [fs:spfadd]
; add ax, word [brResCount] ; 18 + 1 now AX = 19
add ax, word [fs:rescountadd]
; mov WORD[datasector], ax ;
目录起始的扇区
19
lea si, [dword datasector]
mov [si], ax
; add WORD[datasector], cx ;
数据区起始扇区
33
lea si, [dword datasector]
add [si], cx
;
目录放入
0x0200
内存
mov bx, 0x0200
call ReadSec
;
比较目录中是否有
SYS.img
文件存在
; mov cx, WORD [brRootEntries] ; CX:224
在目录的所有文件中寻找
mov cx, [fs:rootentriesadd]
mov ax, fs
mov es, ax
mov di, 0x0200 ;
从目录入口处开始
0x200
.LOOP:
push cx ;
保护
CX = 224
mov cx, SystemFileNameLen ; 8
个文件名称和
3
个扩展名称
lea si, [dword SystemFileName] ;
push di
repe cmpsb ; stop compare if cx >0 or the
; first unequal is met(zf=1)!
pop di
je loadfiledec ;if zf = 1, jmp LOAD_FAT!(Seek OK!)
pop cx
add di, 0x0020 ;
跳到下一个目录入口
loop .LOOP ; cx
自动减
call _NextLine
lea si, [dword NotFound]
call _pntchr
jmp failure
;
载入文件描述子节
loadfiledec:
pop cx ;
有一个
cx
的值没有弹出来
;
把启动的镜像文件
system.img
文件的起始单元保存起来
call _NextLine
lea si, [dword LoadFileDescriptor]
call _pntchr
; call _NextLine
mov dx, [fs:di + 0x001A] ;the file's first cluster
lea si, [dword cluster]
mov [si], dx ; store the first cluster
;
计算
fat
的大小并保存到
07c00:0x0200(ds:bx)
xor ax, ax
mov al, BYTE [fs:fatsadd] ; al:2
mul WORD [fs:spfadd] ; AH:18 = 9*2
mov cx, ax ; CX:18
;
读取数据放入到
0x7c00:0x0200 ds:bx
; mov ax, WORD [brResCount] ; AX:1
mov ax, WORD [fs:rescountadd] ; AX:1
mov bx, 0x0200 ;
call ReadSec ; AX:1 CX:18 BX:0200
;
读取
img
放入
9000:0x1000
处
mov ax, SYSSEG
mov es, ax
mov bx, SYSOFF
push bx
LOAD_IMAGE:
call _NextLine
lea si, [dword LoadSystemImage]
call _pntchr
; mov ax, WORD [cluster] ; cluster to read
lea si, [dword cluster]
mov ax, [si] ; cluster to read
pop bx ; buffer to read into
call ClusterLBA ; convert cluster to LBA
; AX:[cluster] ES:BX[9000:0000](dest)
xor cx, cx
mov cl, BYTE [fs:spcadd] ; CL:1
call ReadSec ; AX:LBA CX:1 BX:0000 ES:0100
push bx
;
计算下一个单元
lea si, [dword cluster]
;mov ax, WORD [cluster] ; identify current cluster
mov ax, [si] ; identify current cluster
mov cx, ax ; copy current cluster
mov dx, ax ; copy current cluster
shr dx, 0x0001 ; divide by two
add cx, dx ; sum for (3/2)
mov bx, 0x200 ; location of FAT in memory
add bx, cx ; index into FAT
mov dx, [fs:bx] ; read two bytes from FAT
test ax, 0x0001
jnz .ODD_CLUSTER
.EVEN_CLUSTER:
and dx, 0000111111111111b ; take low twelve bits
jmp .DONE
.ODD_CLUSTER:
shr dx, 0x0004 ; take high twelve bits
.DONE:
; mov WORD [cluster], dx ; store new cluster
lea si ,[dword cluster]
mov [si], dx ; store new cluster
cmp dx, 0x0FF0 ; test for end of file,>=0x0FF0: end or bad!
jb LOAD_IMAGE ; if dx<0x0ff0 (CF=1), jmp Load_image
DONE:
pop bx ;
有一个多出来的
bx
在
stack
里面
ret
;
回到主程序
,
这时
system.img
;
已经被装在
0x9000:0x1000
的地方
;
只要设置好保护模式的条件就可以跳转了
failure:
call _NextLine
lea si,[dword ErrorMsg]
call _pntchr
call _NextLine
hlt
文件 system.asm
; ==================================
;;
文件
: system.asm
;;
作用
:
调用中断
;; http://blog.csdn.net/flyback
;;
fly-back@163.com
; ==================================
bits 32
org 0x91000
start:
mov ax, 0x10
mov ds, ax
mov ss, ax
mov esp, 0xfff0
int 0x1
int 0x0
hlt
连接文件kernel.ld文件
OUTPUT_FORMAT("binary")
ENTRY(start)
SECTIONS
{
.text 0x90000 : {
*(.text)
}
.data 0x90500 : {
*(.data)
}
.bss : {
*(.bss)
}
}
编译的build.bat文件
nasm -f aout ../asm/kernel.asm -o ../obj/m.o > error.txt
nasm -f aout ../asm/pnt.asm -o ../obj/pnt.o
nasm -f aout ../asm/readdisk.asm -o ../obj/readdisk.o
nasm -fbin -i../inc -o ../img/SYSTEM.img SYSTEM.ASM
ld -T kernel.ld -s -e start ../obj/m.o ../obj/pnt.o ../obj/readdisk.o -o KERNEL.img
编译完成后生成了
:
fatboot.img
KERNEL.IMG
SYSTEM.IMG
然后打开用
winimage
打开
fatboot.img,
把
KERNEL.IMG
和
system.img
放入
fatboot.img
里面
制作bochs的配置文件start.txt
# configuration file generated by Bochs
config_interface: textconfig
display_library: win32
megs: 32
romimage: file=E:/操作系统/Bochs-2.1.1/Bochs-2.1.1/BIOS-bochs-latest, address=0xf0000
vgaromimage: E:/操作系统/Bochs-2.1.1/Bochs-2.1.1/VGABIOS-elpin-2.40
boot: floppy
floppya: 1_44="fatboot.img", status=inserted
floppyb: 1_44="none", status=inserted
ata0: enabled=0
ata1: enabled=0
ata2: enabled=0
ata3: enabled=0
parport1: enabled=1, file="parport.out"
com1: enabled=1, dev=""
usb1: enabled=1, ioaddr=0xff80, irq=10
# no sb16
floppy_bootsig_check: disabled=0
vga_update_interval: 300000
keyboard_serial_delay: 250
keyboard_paste_delay: 100000
floppy_command_delay: 500
ips: 1000000
text_snapshot_check: 0
mouse: enabled=0
private_colormap: enabled=0
i440fxsupport: enabled=0
clock: sync=none, time0=local
# no ne2k
newharddrivesupport: enabled=1
# no loader
log: log.txt
logprefix: %t%e%d
debugger_log: debug.txt
panic: action=ask
error: action=report
info: action=report
debug: action=ignore
pass: action=fatal
keyboard_mapping: enabled=0, map=
keyboard_type: mf
user_shortcut: keys=none
# no cmosimage
E:/操作系统/Bochs-2.1.1/Bochs-2.1.1
是你安装
bochs
的目录
fatboot.img
是刚才生成的那个文件
和启动文件start.bat
bochsdbg -f start.txt –q
然后双击
Start.bat
启动
bochs