加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ReactOS 源码分析 (一) by:ProgrammeBoy

发布时间:2020-12-15 05:02:00 所属栏目:百科 来源:网络整理
导读:ReactOS 源码分析 前言 ReactOS 是一个开源的免费的操作系统 , 它致力于兼容现在最流行的操作系统 windows, 打破微软垄断的局面 , 这里我们为那些默默无闻的开发者致敬 , 他们开发 reactos 没有工资 , 没有补贴 , 没有 … 只有默默的写代码 … 这是一种精神

ReactOS 源码分析

前言

ReactOS是一个开源的免费的操作系统,它致力于兼容现在最流行的操作系统windows,打破微软垄断的局面,这里我们为那些默默无闻的开发者致敬,他们开发reactos没有工资,没有补贴,没有只有默默的写代码这是一种精神..

代码分析

那我们就在最初引导阶段开始分析.首先我们假设我们的机器是i386机型. 引导磁盘是fat32格式.我的Reactos代码在D:/ReactOS/ReactOS_src/,代码版本0.39

1. 系统开始启动

首先机器加电自检,然后检查启动盘,是从光盘还是硬盘启动呢?可能大家都知道,这是在BIOS里面设置的,这里我们是研究已经安装好的系统启动过程,就磁盘启动啦,首先找到启动磁盘,BIOS会检查磁盘的00磁道,1扇区,如果发现其为55aa结尾而且小于512字节就认为他就是一个合法的引导扇扇区(BootSector),然后把这个引导代码加载到0000:7c000,然后跳转到这个地方执行,现在就把所有的控制权交给引导代码了,BIOS里的启动代码是固定在ROM里的,所以系统启动的代码就是那段引导程序代码,前面我们也假设了我们是fat32格式的磁盘.所以我们就从fat32.asm开始吧.

2 f at32.asm

代码位置: D:/ReactOS/ReactOS_src/boot/freeldr/bootsect/fat32.asm

代码如下:

;看了吧,这里就是把他加载到了0000:7c000

org 7c00h

segment .text

bits 16 ;16位程序

start:

jmp short main

nop

/*这里是什么?winhex打开磁盘,选在结构fat32的样式打开就可以看待这些数据了,

数据结构如下

typedef struct _FAT_BOOTSECTOR

{

UCHAR JumpBoot[3]; // Jump instruction to boot code

CHAR OemName[8]; // "MSWIN4.1" for MS formatted volumes

USHORT BytesPerSector; // Bytes per sector

UCHAR SectorsPerCluster; // Number of sectors in a cluster

USHORT ReservedSectors; // Reserved sectors,usually 1 (the bootsector)

UCHAR NumberOfFats; // Number of FAT tables

USHORT RootDirEntries; // Number of root directory entries (fat12/16)

USHORT TotalSectors; // Number of total sectors on the drive,16-bit

UCHAR MediaDescriptor; // Media descriptor byte

USHORT SectorsPerFat; // Sectors per FAT table (fat12/16)

USHORT SectorsPerTrack; // Number of sectors in a track

USHORT NumberOfHeads; // Number of heads on the disk

ULONG HiddenSectors; // Hidden sectors (sectors before the partition start like the partition table)

ULONG TotalSectorsBig; // This field is the new 32-bit total count of sectors on the volume

UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80)

UCHAR Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0.

UCHAR BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present.

ULONG VolumeSerialNumber; // Volume serial number

CHAR VolumeLabel[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory

CHAR FileSystemType[8]; // One of the strings "FAT12 ","FAT16 ",or "FAT "

UCHAR BootCodeAndData[448]; // The remainder of the boot sector

USHORT BootSectorMagic; // 0xAA55

} FAT_BOOTSECTOR,*PFAT_BOOTSECTOR;*/

OEMName db 'FrLdr1.0'

BytesPerSector dw 512

SectsPerCluster db 0

ReservedSectors dw 32

….

main:

;初始化

xor ax,ax ; Setup segment registers

mov ds,ax ; Make DS correct

mov es,ax ; Make ES correct

mov ss,ax ;Make SS correct

mov bp,7c00h

mov sp,7c00h ; Setup a stack

cmp BYTE [BYTE bp+BootDrive],BYTE 0xff ; If they have specified a boot drive then use it

jne CheckSectorsPerFat

mov [BYTE bp+BootDrive],dl ; Save the boot drive

;下面检查参数是否正确

CheckSectorsPerFat:

cmp WORD [BYTE bp+SectorsPerFat],byte 0x00 ; Check the old 16-bit value of SectorsPerFat

jnz CheckFailed ; If it is non-zero then exit with an error

CheckTotalSectors: ; Check the old 16-bit value of TotalSectors & MaxRootEntries

cmp DWORD [BYTE bp+MaxRootEntries],byte 0x00; by comparing the DWORD at offset MaxRootEntries to zero

jnz CheckFailed ; If it is non-zero then exit with an error

CheckFileSystemVersion:

cmp WORD [BYTE bp+FSVersion],byte 0x00 ; Check the file system version word

jna GetDriveParameters ; It is zero,so continue

CheckFailed:

jmp PrintFileSystemError ; If it is not zero then exit with an error

;下面的函数名称都说明了他的作用

GetDriveParameters:

….省略

CalcDriveSize:

省略

;计算出来放在BiosCHSDriveSize里面

LoadExtraBootCode:

; First we have to load our extra boot code at

; sector 14 into memory at [0000:7e00h]

call ReadSectors

jmp StartSearch

;==========================================================

; Reads logical sectors into [ES:BX]

; EAX has logical sector number to read

; CX has number of sectors to read

ReadSectors:

;这里进行的工作是检查是否为LBA模式如果是进行LBA模式读取

; End of bootsector

;

; Now starts the extra boot code that we will store

; at sector 14 on a FAT32 volume

;

; To remain multi-boot compatible with other operating

; systems we must not overwrite anything other than

; the bootsector which means we will have to use

; a different sector like 14 to store our extra boot code

;========================================================

;下面的代码是进行查找freeldr.sys,然后进行加载,加载到0000:8000

StartSearch:

; Now we must get the first cluster of the root directory

mov eax,DWORD [BYTE bp+RootDirStartCluster]

cmp eax,0ffffff8h ; Check to see if this is the last cluster in the chain

jb ContinueSearch ; If not continue,if so then we didn't find freeldr.sys

jmp PrintFileNotFound

ContinueSearch:

mov bx,2000h

mov es,bx ; Read cluster to [2000:0000h]

call ReadCluster ; Read the cluster

; Now we have to find our way through the root directory to

; The OSLOADER.SYS file

xor bx,bx

mov bl,[BYTE bp+SectsPerCluster]

shl bx,4 ; BX = BX * 512 / 32

mov ax,2000h ; We loaded at 2000:0000

mov es,ax

xor di,di

mov si,filename

mov cx,11

rep cmpsb ; Compare filenames

jz FoundFile ; If same we found it

dec bx

jnz FindFile

jmp PrintFileNotFound

FindFile:

mov ax,es ; We didn't find it in the previous dir entry

add ax,2 ; So lets move to the next one

mov es,ax ; And search again

xor di,filename

mov cx,11

rep cmpsb ; Compare filenames

jz FoundFile ; If same we found it

dec bx ; Keep searching till we run out of dir entries

jnz FindFile ; Last entry?

; Get the next root dir cluster and try again until we run out of clusters

mov eax,DWORD [BYTE bp+RootDirStartCluster]

call GetFatEntry

mov [BYTE bp+RootDirStartCluster],eax

jmp StartSearch

FoundFile:

; Display "Loading FreeLoader..." message

mov si,msgLoading ; Loading message

call PutChars ; Display it

xor di,di ; ES:DI has dir entry

xor dx,dx

mov ax,WORD [es:di+14h] ; Get start cluster high word

shl eax,16

mov ax,WORD [es:di+1ah] ; Get start cluster low word

CheckStartCluster:

cmp eax,2 ; Check and see if the start cluster starts at cluster 2 or above

jnb CheckEndCluster ; If so then continue

jmp PrintFileSystemError ; If not exit with error

CheckEndCluster:

cmp eax,0ffffff8h ; Check and see if the start cluster is and end of cluster chain indicator

jb InitializeLoadSegment ; If not then continue

jmp PrintFileSystemError ; If so exit with error

InitializeLoadSegment:

mov bx,800h

mov es,bx

LoadFile:

cmp eax,0ffffff8h ; Check to see if this is the last cluster in the chain

jae LoadFileDone ; If so continue,if not then read the next one

push eax

xor bx,bx ; Load ROSLDR starting at 0000:8000h

push es

call ReadCluster

pop es

xor bx,5 ; BX = BX * 512 / 16

mov ax,es ; Increment the load address by

add ax,bx ; The size of a cluster

mov es,ax

pop eax

push es

call GetFatEntry ; Get the next entry

pop es

jmp LoadFile ; Load the next cluster (if any)

LoadFileDone:

mov dl,[BYTE bp+BootDrive] ; Load boot drive into DL

mov dh,[BootPartition] ; Load boot partition into DH

;看这里是把freeldr加载到0000:8000位置然后跳转到此处

xor ax,ax

push ax ; We loaded at 0000:8000

push WORD 8000h ; We will do a far return to 0000:8000h

retf ; Transfer control to ROSLDR

;下面是fat格式磁盘的解析函数,可以玩下

; Returns the FAT entry for a given cluster number

; On entry EAX has cluster number

; On return EAX has FAT entry for that cluster

GetFatEntry:

shl eax,2 ; EAX = EAX * 4 (since FAT32 entries are 4 bytes)

mov ecx,eax ; Save this for later in ECX

xor edx,edx

movzx ebx,WORD [BYTE bp+BytesPerSector]

push ebx

div ebx ; FAT Sector Number = EAX / BytesPerSector

movzx ebx,WORD [BYTE bp+ReservedSectors]

add eax,ebx ; FAT Sector Number += ReservedSectors

mov ebx,DWORD [BYTE bp+HiddenSectors]

add eax,ebx ; FAT Sector Number += HiddenSectors

pop ebx

dec ebx

and ecx,ebx ; FAT Offset Within Sector = ECX % BytesPerSector

; EAX holds logical FAT sector number

; ECX holds FAT entry offset

; Now we have to check the extended flags

; to see which FAT is the active one

; and use it,or if they are mirrored then

; no worries

movzx ebx,WORD [BYTE bp+ExtendedFlags] ; Get extended flags and put into ebx

and bx,0x0f ; Mask off upper 8 bits,now we have active fat in bl

jz LoadFatSector ; If fat is mirrored then skip fat calcs

cmp bl,[BYTE bp+NumberOfFats] ; Compare bl to number of fats

jb GetActiveFatOffset

jmp PrintFileSystemError ; If bl is bigger than numfats exit with error

GetActiveFatOffset:

push eax ; Save logical FAT sector number

mov eax,[BYTE bp+SectorsPerFatBig] ; Get the number of sectors occupied by one fat in eax

mul ebx ; Multiplied by the active FAT index we have in ebx

pop edx ; Get logical FAT sector number

add eax,edx ; Add the current FAT sector offset

LoadFatSector:

push ecx

; EAX holds logical FAT sector number

; Check if we have already loaded it

cmp eax,DWORD [FatSectorInCache]

je LoadFatSectorAlreadyLoaded

mov DWORD [FatSectorInCache],eax

mov bx,7000h

mov es,bx

xor bx,bx ; We will load it to [7000:0000h]

mov cx,1

call ReadSectors

LoadFatSectorAlreadyLoaded:

mov bx,bx

pop ecx

mov eax,DWORD [es:ecx] ; Get FAT entry

and eax,0fffffffh ; Mask off reserved bits

ret

FatSectorInCache: ; This variable tells us which sector we currently have in memory

dd 0ffffffffh ; There is no need to re-read the same sector if we don't have to

; Reads cluster number in EAX into [ES:0000]

ReadCluster:

; StartSector = ((Cluster - 2) * SectorsPerCluster) + ReservedSectors + HiddenSectors;

….

; Displays a file not found error message

; And reboots

PrintFileNotFound:

mov si,msgFreeLdr ; FreeLdr not found message

call PutChars ; Display it

mov si,msgAnyKey ; Press any key message

call PutChars ; Display it

jmp Reboot

msgFreeLdr db 'freeldr.sys not found',0dh,0ah,0

filename db 'FREELDR SYS'

msgLoading db 'Loading FreeLoader...',0

times 1022-($-$$) db 0 ; Pad to 1022 bytes

dw 0aa55h ; BootSector signature

,看完代码也有单晕晕乎乎了,我们来总结下fat32.asm。首先加载到0000:7c00,接下来就是那个结构体,而上面跳转到main函数那了.开始当然是对一些寄存器的初始化,接着就是检查BootSector的参数是否正确,接着计算整个磁盘的存储量,为什么要计算这个呢?为了检查磁盘是否支持LBA模式。再下面的工作就是查找freeldr.sys.并将其加载到内存0000:8000,

其中又有fat文件格式的操作….

需要的知识点:

1,汇编是必要的.

2,bootsector.

3,fat32文件系统解析

4,怎么检查是否支持LBA模式

5,int 10,int 13 貌似都会吧..

6,得会使用nasm编译呀!!

对了freeldr目录下有个note.txt里面有内存分配表如下,大家好好看看:

Memory layout:

0000:0000 - 0000:0FFF: Interrupt vector table & BIOS data

0000:1000 - 0000:6FFF: Real mode stack area

0000:7000 - 0000:7FFF: Cmdline (multiboot)

0000:8000 - xxxx:xxxx: FreeLoader program & data area

xxxx:xxxx - 7000:7FFF: Random memory allocation heap

7000:8000 - 7000:FFFF: Protected mode stack area

8000:0000 - 8000:FFFF: File system read buffer

9000:0000 - 9000:FFFF: Disk read buffer for BIOS Int 13h

A000:0000 - FFFF:FFFF: reserved

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读