启动系统,并进入pro模式!
如果软盘有kernerl.bin,就执行!
系统使用fat格式,并用winimage写入数据
kernerl.bin的读取有bug只能读连续扇区,部分代码引自网络
[bits 16]
[org 0x7c00] ; 告诉编译器程序加载到7c00处
CATALOG equ 0x7E00 ;catalog loaded at 0x7e00
KERNEL equ 0x500 ;kernel.bin loaded at 0x500.
jmp Start
; 引导区文件系统数据
;----------------------------------------------------------------------------
brOEM DB " T's OS " ; 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 'NO NAME ' ; 002Bh - 卷标
brFSID DB 'FAT12 ' ; 0036h - 系统保留
;------------------------------------------------------------------------
Start:
mov ax, cs
mov ds, ax
mov es, ax
mov ax,0x8000 ;栈放在0x1F00段里,这里栈有问题(栈放在0x1F00段里)!!!!!!!!!!!!!!!
mov ss,ax
mov sp,0xffff ; 堆栈入口
call DispStr ; 调用显示字符串例程
call LoadFile ; 把目录区读入到200的地方
call FindFile ; 在200的地方找把kernel.bin,读出来并显示读取成功
;=============================================
;SwitchPro建立GDT,进入保护模式
;=============================================
SwitchPro;
; 打开A20
in al, 92h
or al, 00000010b
out 92h, al
; end 打开A20
; 设置GDT
cli
;mov ax,KERNEL ; lgdt 指令加载 gdtr 是以ds为数据段加载
;mov ds,ax
;lea si, [dword gdtr]
lgdt [gdtr]
;lea si, [dword idtr]
;lidt [dword gdtr]
mov eax, cr0
or eax,1
mov cr0, eax
jmp dword selcode:CODE32 ;
;jmp KERNEL ;跳到kenel.bin开始执行内核
[bits 32]
CODE32:
sti
mov eax,codesel_gdt
mov ebx,datasel_gdt
mov ax,ProMessage
mov bp,ax
mov cx,ProMsglength
jmp $ ; 到此停止!!!!!!!!!!!!!!!!!!!!!!!
[bits 16]
;===================================================================
;初始化gdtr和gdt
;===================================================================
gdtr:
dw gdt_end - gdt-1 ; gdt的长度--16位(800H)GDT界限gdt limit=2048, 256 GDT entries
;这里应该是伪长度7,15,23,31,因为从0开始计算的
dd gdt
;===================================================================
;初始化gdtr和gdt
;===================================================================
gdtr:
dw gdt_end - gdt-1 ; gdt的长度--16位(800H)GDT界限gdt limit=2048, 256 GDT entries
;这里应该是伪长度7,15,23,31,因为从0开始计算的
dd gdt ; gdt的物理地址--32位GDT基地址
;0x00007c930017!!!!!!!!
gdt:
gdt0:
dw 0,0,0,0 ; 一定要为0
codesel_gdt:
dw 0xffff ; 界限Limit值 = 0x100000 * 0x1000 = 4GB
dw 0x0000 ; 基地址 = 0
db 0x00
db 0x9A ; 表示 存在 可执行可读代码段
db 0xCF ; 粒度以及32位代码1100=0XC
db 0x00
datasel_gdt:
dw 0xffff ; 界限4GB
dw 0x0000 ; 基地址
db 0x00
db 0x92 ; 表示 存在 可读写数据段
db 0xCF ; 粒度以及数据锻大小4G,1100=0XC
db 0x00
gdt_end:
selcode equ codesel_gdt - gdt ;索引值1,2,3....
seldata equ datasel_gdt - gdt
;=============================================
;DispStr 显示boot已经启动!
;=============================================
DispStr:
mov ax, BootMessage
mov bp, ax ; es:bp = 串地址
mov cx, Msglength ; cx = 串长度
call PrintMsg
ret
;=============================================
;LoadFile 把目录从软盘中读出来!
;=============================================
LoadFile:
mov ax,19 ;开始的扇区
mov bx,CATALOG ;目录放在7E00H的地方!!!!!!!!!!!!!!!!!!!!!!!!!!!
mov cx,14 ;目录扇区个数
loopreadsec:
push ax
push bx
push cx
call LBACHS ; 调用转换
mov dl, 0 ; 因为是a:所以为0!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
mov ah, 0x02 ; BIOS 读取扇区命令
mov al, 0x01 ; 一个扇区
int 0x13 ; 调用中断
nop
pop cx
pop bx
pop ax
add bx,200
inc ax
loop loopreadsec
ret
;=============================================
; 转换逻辑块访问为读取磁盘所使用的磁道,盘面,扇区
; 相对扇区 = (逻辑扇区 / 每磁道扇区数) + 1
; 相对盘面 = (逻辑扇区 / 每磁道扇区数) MOD 盘面数
; 相对磁道 = 逻辑扇区 / (每磁道扇区数 * 盘面数)
;=============================================
LBACHS:
xor dx, dx ; dx = 0
mov cx,18
div cx ; div: ax/18 -> 商:ax 余数:dx
inc dl ;sec ;
mov cl, dl ;sector
xor dx, dx ; dx = 0
push bx
mov bx,2
div bx ; ax/2 -> 商:ax 余数:dx
pop bx
mov ch, al ; track
mov dh, dl ; head
ret
;=============================================
;FindFile 查找文件名,并且装到0x500,显示Load Kernel.bin Success!
;=============================================
FindFile:
cld ;地址自动增加
mov cx,224 ;根目录共有224个文件
mov di,CATALOG ;目录放在7E00H的地方!!!!!!!!!!!!!!!!!!!!!
.l_findfile:
push cx
lea si,[Kernel] ;?
push di
mov cx,11 ;8+3=0xb文件名和后缀长度
repe cmpsb
pop di
je findfile_ok
add di,32 ;开始找下1个文件
pop cx
loop .l_findfile
mov ax, LoadKerFail ;失败
mov bp, ax ; es:bp = 串地址
mov cx, LoadKerFaillength ; cx = 串长度
call PrintMsg
ret
findfile_ok:
pop cx
add di,26 ;取文件占用的第一个簇号,即起始簇
mov ax,[di]
add ax,31 ;簇转成扇区
mov bx,KERNEL ;文件放在0x500!!!!!!!!!!!!!!!!!!!!!!!!!!!
call LBACHS ; 调用转换
mov dl, 0 ; 因为是a:所以为!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
mov ah, 0x02 ; BIOS 读取扇区命令
mov al, 0x03 ; 一个扇区,这里应该根据文件大小来决定!!!!!
int 0x13 ; 调用中断,内核放在0x1e00!
mov ax, LoadKerSuess ;成功
mov bp, ax ; es:bp = 串地址
mov cx, LoadKerlength ; cx = 串长度
call PrintMsg
ret
;=============================================
;显示信息
;=============================================
PrintMsg:
mov ax, 01301h ; ah = 13, al = 01h
mov bx, 000ch ; 页号为0(bh = 0) 黑底红字(bl = 0Ch,高亮)
mov dl, 0
mov dh, BYTE [NoLine]
int 10h ; 10h 号中断
add dh,1
mov BYTE [NoLine],dh
ret
BootMessage: db "Welcome to T's OS!",0x0D,0x0A
Msglength equ $-BootMessage
DB 0x00
Kernel: db 'KERNEL BIN' ;8+3=11位;将来这里改成内核的文件名!!!!!!!!!!!!!
LoadKerSuess: db 'Load Kernel.bin Success!',0x0D,0x0A
LoadKerlength equ $-LoadKerSuess
DB 0x00
LoadKerFail: db 'Load Kernel.bin Fail!',0x0D,0x0A
LoadKerFaillength equ $-LoadKerFail
DB 0x00
ProMessage: db "I'm in the Pro Mode!",0x0D,0x0A
ProMsglength equ $-ProMessage
DB 0x00
NoLine DB 0x00
times 510-($-$$) db 0 ; 填充剩下的空间,使生成的二进制代码恰好为512字节
dw 0xaa55 ; 结束标志
;把这段代码用NASM编译一下:
;nasm boot.asm –o boot.bin
版权声明:本文为博主原创文章,未经博主允许不得转载。
分享到:
相关推荐
6. 分区表:在MBR中,除了Bootloader代码之外,还包含了磁盘的分区表信息。分区表描述了磁盘上分区的布局,每个分区的起始和结束位置、分区类型等。理解分区表对于引导过程至关重要,因为操作系统需要通过它来定位和...
芥末内核使用NASM进行汇编语言编程,这是编写低级代码,如启动加载器和与硬件交互的常用工具。同时,C语言用于编写更高级的抽象层和系统服务,因为它提供了模块化和可读性更强的代码结构。 首先,我们需要了解NASM...
1. **源代码**:引导加载器的源代码通常用汇编语言或C语言编写,以实现高效且对硬件的直接控制。源代码可能分为两个阶段,阶段一可能包含汇编语言编写的小型代码,用于初始化CPU和基本输入输出系统(BIOS/UEFI),...
可能包括源代码、编译工具、文档教程等,帮助开发者或学习者了解如何编写简单的引导加载器程序,从而深入理解操作系统启动过程。 【标签】: "Example_First_Pr" 暗示这是一次初级的实践尝试,针对引导加载器的初学...
学生使用fillout.cpp填充代码到软盘映像的首扇区,并使用msys2和NASM进行汇编和编程。 【问题与解决方案】 在实验过程中遇到的问题是nasm不支持masm的`assume`伪指令。解决方法是查阅nasm的文档,学习其语法特性,...
在《自己动手写操作系统》这本书中,作者引导读者深入理解操作系统的原理,并通过实际编写代码来实现一个简单的操作系统。这是一次理论与实践相结合的学习过程,能够帮助读者对操作系统有更直观的认识。 一、操作...
一旦BIOS找到了可引导设备,它会将设备的第一个扇区内容复制到内存的物理地址[0x7C00]处,然后跳转到该地址执行代码,这就是所谓的引导加载器(bootloader)。引导加载器的任务是加载内核到内存的物理地址[0x100000]...
"自己动手写操作系统源码"的主题旨在帮助学习者深入理解操作系统的内部工作原理,通过实践编写操作系统源码,从而获得宝贵的洞察力。 描述中提到的“进入OS内核最佳入门书籍”表明这是一份适合初学者的学习资料,它...
7. **NASM(Netwide Assembler)**:NASM是用于x86架构的开源汇编器,可能被用于编译Cyjon的汇编源代码。 8. **System Programming**:系统编程涉及创建和维护操作系统组件,如设备驱动、内核模块等。在Cyjon项目中...
在实际操作中,开发者需要先编写bootloader(引导加载器),这部分代码通常位于软盘的主引导记录(MBR)中,它的任务是加载更复杂的启动代码或内核到内存中。接着,内核会初始化硬件环境,如内存管理、中断处理,并...
当计算机启动时,BIOS会读取硬盘的第一个扇区(即引导扇区)到内存的0x7C00地址,然后将控制权转移给这段代码,即Bootloader。Bootloader负责加载操作系统的剩余部分到内存中,通常是将CS:IP设置为操作系统在内存的...
另外,如果您恰巧在NASM程序集中编写全部或部分内核代码,您将很高兴地知道引导程序代码中已经提供了打印例程以及磁盘加载例程。 要使用它们,只需在print例程中包含disk.asm ,在diskload例程中包含print.asm ...
在"压缩包子文件的文件名称列表"中,我们看到"FAT12-Bootloader-master"可能是一个项目源代码仓库的名称,暗示着包含了一个FAT12引导加载器的实现,可能是用NASM编写的,并且是项目的主分支或最终版本。这个仓库可能...
5. **编译与测试**:使用交叉编译工具链(如NASM和GCC)将源代码编译成可执行文件,并使用QEMU这样的模拟器进行测试。 **三、提供的资源** 压缩包中的`GeekOS Project0_罌粟花田_百度空间.mht`文件可能是对项目0...
2. **汇编语言(Assembly)**:尽管主要使用C语言,但在处理低级别任务如初始化硬件或跳转到C代码时,汇编语言(如NASM,Netwide Assembler)是必不可少的。i386和i686标签表明该内核可能兼容32位和64位的Intel架构...
学习如何用C语言编写操作系统代码,如内核、驱动程序等,是课程中的重要组成部分。 5. **汇编语言**:虽然高级语言如C提供了抽象,但汇编语言对于理解计算机底层工作原理至关重要。在TIP-OSFS中,学员将学习如何...
在这个阶段,读者可能会学习到如何组织和管理操作系统源代码,以及如何使用版本控制系统如Git来追踪代码变更。 3. **z_osabin**: "osabin"很可能是指操作系统的核心二进制文件,比如内核映像。这个阶段的学习涵盖了...
- 使用NASM汇编器编译引导扇区源代码。 - 命令行示例:`nasm boot.asm -o boot.bin` 2. **创建磁盘映像**: - 使用`dd`命令将编译后的二进制文件写入到磁盘映像文件中。 - 命令行示例:`dd if=boot.bin of=a....
8. **C语言编程**:尽管部分内核代码可能使用汇编编写,但大部分功能会用C语言实现,因为它提供了更高的抽象层次和可移植性。掌握C语言基础和指针操作对于编写内核代码极其重要。 9. **编译和调试**:学习如何使用...
nasm则用于编写内核中的汇编代码,这些代码通常涉及处理器的直接操作,如设置寄存器、管理中断等。 在mikanOS中,文件系统也是一项重要组成部分。虽然它可能不像大型操作系统那样复杂,但仍然需要实现文件的创建、...