操作系统入门(六) - 2 - 加入中断在保护模式试试看
来源:互联网 发布:fm奥克斯福德数据 编辑:程序博客网 时间:2024/05/16 11:56
加入中断试试看
2006-5-20 blog.csdn.net/flyback fly-back@163.com
一直都没有考虑中断,现在在保护模式下把中断加上去看看是怎么回事
现在的文件有:
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
;; fly-back@163.com
; ==================================
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
;; mailto:fly-back@163.com
;; ===================================
%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
- 操作系统入门(六) - 2 - 加入中断在保护模式试试看
- 操作系统实验七:保护模式之中断测试实验
- 保护模式中断
- 80386在保护模式下的中断和异
- 80386在保护模式下的中断和异
- 80386在保护模式下的中断和异
- 保护模式与操作系统
- 操作系统和保护模式
- 保护模式编程、六
- RayCommand操作系统的实现笔记2--完成在保护模式Text Mode下,输出字符
- 写操作系统(六)执着 实模式与保护模式对比学习
- 【操作系统原理】保护模式下Intel 80x86 CPU 硬件中断过程
- 操作系统学习笔记——保护模式——中断和异常(1)
- DOS保护模式下中断
- 操作系统实验六:保护模式之使用调用门提升特权级
- 操作系统保护模式Protected Mode
- 操作系统实现之保护模式
- 操作系统实现之保护模式
- 乱
- MIS 工業化...路漫長
- 从ORACLE向SQL SERVER定时迁移实现
- 如何拖动无标题窗体
- 谈基于.net平台windows开发中的模式窗体
- 操作系统入门(六) - 2 - 加入中断在保护模式试试看
- JSF学习
- Advanced PDF Password Recovery Pro 2
- etch 2.6.15下面建立编译模块的环境
- Java与C++函数参数传递比较——C++学习笔记一
- 世界名牌详解
- Microsoft JET Database Engine (0x80004005)未指定的错误
- 基于Delphi的网上视频聊天软件
- 迷茫女孩,大家指点一下吧谢啦