`
- 浏览:
235020 次
- 性别:
- 来自:
北京
-
实现OS中BOOTLOADER过程,并进入保护模式的代码
- ;;;;;;;实现进入进入保护模式,简单实现gdt,还没实现idt,用fat格式,这样利于内核文件的扩展。编写好内核之后,
- ;;;;;;;;可以直接放到软盘的根目录下。不需要在用镜像文件写入磁盘。
- ;;;;;;;;内存分配,堆栈在8FFFF,内核在500H,目录文件名被读取到7E00,等待扩展保护模式中断,完善磁盘读文件过程
- [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 ; 堆栈入口 8FFFF
- call DispStr ; 调用显示字符串例程
- call LoadFile ; 把目录区读入到200的地方,bios
- call FindFile ; 在7E00的地方找kernel.bin,读出来放到500的地方,并显示读取成功
- call Clrscr ;先清屏
- ;=============================================
- ;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:0 ;进入保护模式,并且跳到下面的段中
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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
- ;call PrintMsg ;保护模式中断有问题,需要修改这里,最好能利用实模式下的bios中断程序。
- ;===================
- mov ax,videosel ; 初始化gs,使其指向显示内存
- mov gs,ax
- mov word [gs:0],0x741 ; 在保护模式下显示一个白色的字符A
- ;===================
- 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 ; gdt的物理地址--32位GDT基地址
- ;0x00007c930017!!!!!!!!
- gdt:
- gdt0:
- dw 0,0,0,0 ; 一定要为0
- codesel_gdt:
- dw 0xffff ; 界限Limit值 = 0x100000 * 0x1000 = 4GB
- dw CODE32;0x0000 ; 基地址 = CODE32.!!!!!!!是不是最好设置从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
- ;========================
- videosel equ $-gdt
- dw 3999
- dw 0x8000 ; 基址是0xb8000
- db 0x0b
- db 0x92
- db 0x00
- 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:所以为0!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- 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
- ;=============================================
- ;清屏
- ;=============================================
- Clrscr :
- mov ax,0x0600 ; 使用中断10h的功能6,实现卷屏,如果al=0则清屏
- mov cx,0x0000 ; 清屏
- mov dx,0x174f ; 卷屏至23,79
- mov bh,0 ; 使用颜色0来填充
- int 0x10 ; 调用10h中断
- 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
- ;应该把内核在pro模式下加载就对了!
分享到:
Global site tag (gtag.js) - Google Analytics
相关推荐
4. **错误处理**:在加载过程中如果遇到问题,Bootloader需要有适当的错误处理机制,如重试、跳过损坏部分或者进入安全模式。 5. **用户交互**:一些Bootloader支持用户通过串口、键盘或其他接口进行交互,如选择...
- **加载OS映像**:Bootloader会读取存储在Flash或其他非易失性存储器中的操作系统镜像,并将其加载到内存的适当位置。 - **系统配置**:可能涉及网络配置、串口设置等,以便与外部设备或服务器通信。 - **用户...
3. **实模式到保护模式的转换**:在bootloader中,转换的关键步骤包括清零标志、开启A20线以启用32位地址空间、初始化全局描述符表(GDT)、设置控制寄存器cr0的PE位以进入保护模式,以及设置段寄存器和堆栈。...
1. 编写Bootloader:这部分代码需要在16位实模式下编写,负责切换到保护模式,并加载kernel到内存的适当位置。 2. 遵循Multiboot规范:在Bootloader中设置特定的内存标签和魔术数,以告知引导加载器这是一个符合...
同时,还会关闭中断并清除方向标志,以准备好进入保护模式。 4. **开启A20**:A20地址线的开启是实模式到保护模式转换的关键步骤。在实模式下,由于A20线被关闭,CPU只能访问1MB的内存。开启A20允许访问超过1MB的...
### 任务4:Bootloader - 进入保护模式 Bootloader是操作系统启动的第一部分,它的任务是将系统从实模式切换到保护模式,以便后续的OS可以安全地运行。在启动过程中,CPU首先执行位于物理地址0x7c00处的代码,此时...
本文将深入探讨ARM处理器的启动过程,以及相关代码的设计和实现。ARM启动代码,也称为引导加载器(Bootloader),是系统上电后执行的第一段程序,它的任务是初始化硬件环境,加载操作系统映像到内存,为后续的操作...
bootloader是一种小型软件,它的主要任务是加载并初始化操作系统,使得计算机能够从实模式切换到保护模式,然后执行更复杂的操作系统代码。在这个lab1中,我们将关注bootloader的实现、ucore的操作系统核心以及它们...
在x86架构中,通常会先加载16位实模式的简单代码,然后切换到32位或64位保护模式,以便进行更复杂的操作。 `Makefile`是构建工程的配置文件,包含了编译、链接等步骤的规则。学生可能需要编写或修改Makefile来编译...
这部分主要介绍了计算机启动过程中的一些基础知识,尤其是使用gdb进行调试的方法以及如何从16位实模式转换至32位保护模式。 ##### 2.1 练习2 - **设置断点**:在gdb中设置断点,使用命令`(gdb)b*0x7c00`。这一步是...
- 在32位CPU上,系统启动时默认处于实模式,单任务运行,直至操作系统加载并切换到保护模式。 3. **启动流程**: - **CPU初始化**:CPU的寄存器被设置,如CS和IP分别设置为0xFFFF和0,执行位于0xFFFF0的跳转指令...
在实验中,Bootloader需要切换到保护模式,这是一种更安全的模式,允许使用分页机制和更多的内存地址空间。 CPU的中断机制在实验中扮演了重要角色,因为操作系统需要响应硬件事件,如时钟中断或外设请求。...
HelloOS选择在这个平台上运行,意味着它必须处理32位寻址、保护模式、中断向量表等一系列与硬件紧密相关的特性。 开源社区的参与是HelloOS能够持续发展和改进的关键。开发者们可以通过提交补丁、讨论问题和分享想法...
Bootloader通常是设备制造商锁定的,以保护设备安全,但刷机过程往往需要解锁Bootloader,以便能够安装自定义的启动文件。 2. **内核(Kernel)**:内核是操作系统的核心部分,负责管理硬件资源,如CPU、内存和设备...
7. **刷机**:有了解锁的Bootloader和第三方Recovery,用户可以自由地刷入非官方系统,如LineageOS或其他基于Android的定制系统,以实现更多功能或性能优化。 8. **恢复与更新**:解锁后的设备仍可以接收官方系统...
- 确保STM32进入编程模式,通常是通过特定的引脚配置或硬件开关来实现。 - 固件文件应与目标STM32芯片的型号和配置相匹配,否则可能无法正常运行。 总的来说,FLYMCU作为STM32串口下载软件,极大地简化了STM32开发...
同时,关闭手机并进入Bootloader模式(通常按音量下键+电源键组合)。 2. **启用USB调试**:在手机的“开发者选项”中开启USB调试,便于电脑与手机连接。 3. **下载工具**:从官方或可靠的第三方网站下载MVT-HTC解锁...
这通常包括备份重要数据、关闭手机、进入Fastboot模式、连接电脑并运行解锁工具等步骤。 3. **风险与注意事项**:解锁Bootloader会清除所有用户数据,因此在开始之前必须做好完整的数据备份。此外,解锁可能会使...
Bootloader是手机启动时运行的第一段代码,通常为了保护设备安全,新买的一加手机Bootloader会默认处于锁定状态,不允许用户进行自定义系统级别的操作。但对许多资深用户来说,解锁Bootloader是刷机、安装第三方ROM...
Bootloader负责初始化硬件,加载操作系统映像到内存,并将其控制权交给OS。 2. **Bootloader阶段**:Bootloader分为阶段1和阶段2。阶段1代码通常驻留在只读存储器中,用于初始化CPU和必要的外围设备;阶段2负责更...