In the first two sections, we loaded a piece of code into system memory through a floppy disk, and instructed the CPU to execute the code that was added to the memory, in fact, the operating system kernel was loaded. But we load the code, the maximum can only be a byte, an operating system kernel, less than hundreds of trillion, thus, the system kernel can not directly read into the system memory from the floppy disk.
As a general rule, a program of bytes loaded into memory is actually a kernel loader that, after it runs, loads the kernel code stored on disk into the specified memory space by reading the disk, and then commits the CPU control to the loaded system kernel.
This requires us to understand the physical structure of the floppy disk and the data-reading method of the floppy disk.
The physical structure of a floppy disk, such as a disk is divided into a number of circles, such as the gray circle, which we call a track, also known as a cylinder, a track or cylinder, and is divided into several parts, each part, we call a sector, a sector size is exactly 512k, thus, When we store the data on a floppy disk, the data is decomposed into chunks of 512Byte size and then written to the sector.
To read the data, the head moves to the track or cylinder where the sector is located, and then the disk rotates, and when the sector to be read goes directly below the head, the magnetic head powers up and the data in the sector is read into memory by the electromagnetic effect.
From the left side of the graph can be understood that a disk has two disk surface, each surface composition is the same as the right graph, and each disk face a head, so when you want to read data from the disk, you need to determine which disk face, to determine which head to use to read the data, and then determine which track, Finally, determine which sector the data to read is stored in.
For the system we want to develop, we want to simulate a 3.5-inch floppy disk, the characteristics of this floppy disk is that it has two disk surface, so it corresponds to two heads, each disk has 80 tracks, that is, the cylinder, the number is 0-79. Each cylinder has 18 sectors with a number of 1-18 respectively. So the amount of data a disk can store is:
512 * 18 * 80
A floppy disk has two disks, so the data a floppy disk can store is:
2 * * * * * = 1474560 Byte = 1440 KB = 1.5M
Next, we use Java to simulate a 3.5-inch floppy disk, and its read-write logic.
Floppy.java for implementing virtual floppy disks
Import Java.io.dataoutputstream;import Java.io.fileoutputstream;import Java.util.arraylist;import Java.util.HashMap; Public classFloppy {enumMagnetic_head {magnetic_head_0, magetic_head_1}; Public intSector_size = +;Private intCylinder_count = the;//80 cylinders Private intSectors_count = -;PrivateMagnetic_head Magnetichead = Magnetic_head. Magnetic_head_0;Private intCurrent_cylinder =0;Private intCurrent_sector =0;Privatehashmap<integer,arraylist<arraylist<byte[]>> > Floppy =Newhashmap<integer,arraylist<arraylist<byte[]>> > ();//One disk Two Faces Public Floppy() {initfloppy (); }Private void Initfloppy() {//A disk has two disk facesFloppy.put (Magnetic_head. Magnetic_head_0.ordinal (), Initfloppydisk ()); Floppy.put (Magnetic_head. Magetic_head_1.ordinal (), Initfloppydisk ()); }Privatearraylist<arraylist<byte[]>>Initfloppydisk() {arraylist<arraylist<byte[]>> Floppydisk =Newarraylist<arraylist<byte[]>> ();//A face of the disk //A disk face with 80 cylinders for(inti =0; i < Cylinder_count; i++) {Floppydisk.add (Initcylinder ()); }returnFloppydisk; }Privatearraylist<byte[]>Initcylinder() {//Construct a cylinder with 18 sectors on a cylindrical surfacearraylist<byte[]> cylinder =Newarraylist<byte[]> (); for(inti =0; i < Sectors_count; i++) {byte[] Sector =New byte[Sector_size]; Cylinder.add (sector); }returnCylinder } Public void Setmagnetichead(Magnetic_head HEAD) {magnetichead = head; } Public void Setcylinder(intCylinder) {if(Cylinder <0) { This. Current_cylinder =0; }Else if(Cylinder >= the) { This. Current_cylinder = -; }Else{ This. Current_cylinder = cylinder; } } Public void Setsector(intSector) {//sector number from 1 to if(Sector <0) { This. Current_sector =0; }Else if(Sector > -) { This. Current_sector = --1; }Else{ This. Current_sector = Sector-1; } } Public byte[]Readfloppy(Magnetic_head HEAD,intCylinder_num,intSector_num) {setmagnetichead (head); Setcylinder (Cylinder_num); Setsector (Sector_num); arraylist<arraylist<byte[]>> disk = floppy.Get( This. magnetichead.ordinal ()); arraylist<byte[]> cylinder = disk.Get( This. Current_cylinder);byte[] sector = cylinder.Get( This. Current_sector);returnSector } Public void Writefloppy(Magnetic_head HEAD,intCylinder_num,intSector_num,byte[] buf) {setmagnetichead (head); Setcylinder (Cylinder_num); Setsector (Sector_num); arraylist<arraylist<byte[]>> disk = floppy.Get( This. magnetichead.ordinal ()); arraylist<byte[]> cylinder = disk.Get( This. Current_cylinder); Cylinder.Set( This. Current_sector, BUF); } Public void Makefloppy(String fileName) {Try{DataOutputStream out=NewDataOutputStream (NewFileOutputStream (FileName)); for(intHead =0; Head <= Magnetic_head. Magetic_head_1.ordinal (); head++) { for(intCylinder =0; Cylinder < Cylinder_count; cylinder++) { for(intSector =1; Sector <= Sectors_count; sector++) {byte[] buf = Readfloppy (Magnetic_head.values () [HEAD], cylinder, sector); out. write (BUF); } } } }Catch(Exception e) {//TODO auto-generated catch blockE.printstacktrace (); } }}
Read and write virtual floppy disk needs to call the structure readfloppy or writefloppy, use these interfaces must specify the head, cylinder and sector area code, in the main program, I will compile the compilation of the operating system kernel to the virtual floppy disk, and then the virtual floppy disk file, the code is as follows:
ImportJava.io.DataOutputStream;ImportJava.io.File;ImportJava.io.FileInputStream;ImportJava.io.FileNotFoundException;ImportJava.io.FileOutputStream;ImportJava.io.IOException;ImportJava.io.InputStream;ImportJava.util.ArrayList; Public class operatingsystem { PrivateFloppy Floppydisk =NewFloppy ();Private void Writefiletofloppy(String fileName) {File File =NewFile (FileName); InputStream in =NULL;Try{in =NewFileInputStream (file);byte[] buf =New byte[ +]; buf[510] =0x55; buf[511] = (byte)0xaa;if(In.read (BUF)! =-1) {//Read the kernel into disk No. 0, No. 0 cylinder, 1th sectorFloppydisk.writefloppy (Floppy.magnetic_head. Magnetic_head_0,0,1, buf); } }Catch(IOException e) {E.printstacktrace ();return; } } Public OperatingSystem(String s) {Writefiletofloppy (s); } Public void makefllopy() {Floppydisk.makefloppy ("System.img"); } Public Static void Main(string[] args) {OperatingSystem op =NewOperatingSystem ("Boot.bat"); Op.makefllopy (); }}
After the above code is run, a system.img virtual floppy file is generated at the root of the project, and the floppy disk is added to the virtual machine, and the operating system kernel we make can be executed by the virtual machine:
The above code can be downloaded using the following GIT commands:
git clone https://github.com/wycl16514/OS-kernel-development.git
Using assembly language to realize floppy disk reading and writing
The use of the assembly to read the floppy disk is the same as described above, we want to call the corresponding BIOS interrupt, while the magnetic number, cylinder, the sector area code to be read to the interrupt code, read the assembly code of the floppy disk as follows:
mov CH, 1; CH is used to store the cylinder number
mov DH, 0;D H used to store magnetic number one
mov CL, 2; CL is used to store the sector code
mov BX, msg; ES:BX Data Storage Buffers
mov AH, 0x02; AH = 02 Indicates that a read-disk operation is to be done
mov AL, 1; AL says to practice reading several sectors
mov DL, 0; Drive number, general we only have one floppy drive, so write dead
; for 0
INT 0x13; Call BIOS interrupt to implement disk read function
JC error; If there is an error reading the disk, jump to the error to execute the corresponding code
In the computer hardware, there is an implied register called FLACs, when the BIOS call error, the FLACS register CF bit will be set 1, while the error code into AH, if not wrong, then the FLACs register of CF bit will be 0, so JC error means:
if (FLACs. CF = = 1) {
Error ();
}
In front, our kernel is loaded into memory and a statement is printed, and the statement is stored in the same sector as the kernel code, and this time, the statement we are going to print is stored in the second sector of the first cylinder, and after the kernel is loaded like memory, the statement that will be printed is read from the specified location by the BIOS. And then display it on the screen with the following code:
Org0x7c00;jmpEntrydb0x90Db"Oskernel"Dw +Db1Dw1Db2Dw224Dw2880Db0xf0Dw9Dw -Dw2Dd0Dd2880Db0,0,0x29Dd0xFFFFFFFFDb"Myfirstos"Db"FAT12"Resb -Entry: movAx0 movSS, AxmovDS, AxmovES, axmovSi, msgReadfloppy: movCh1 ; CH is used to store the cylinder number movDh0 ;D h is used to store the magnetic number movCl2 ; CL is used to store the sector code movBX, MSG; ES:BX Data Storage Buffers movAH,0x02 ; AH = 02 Indicates that a read-disk operation is to be done movAL,1 ; AL says to practice reading several sectors movClass0 ; drive numbering, generally we only have one floppy drive, so write dead ; for 0Int0x13 ; Call BIOS interrupt to implement disk read functionJC ErrorPutloop: movAL, [Si]AddSi1CMP al,0Je finmovAh0x0e movBx theInt0x10 jmpPutloopFin:HLTjmpFinError: movSi, errmsg; error printing errors jmpPutloopmsg:Resb -ErrMsg:Db"Error"
In the assembly code above, Readfloppy will print the string from the disk read out, put into the buffer msg, you notice, MSG below is the statement Resb 64, which means to allocate 64 bytes of buffer.
Save the assembly code above as a file boot.asm and then use the command:
NASM Boot.asm-o Boot.bat
Compile the above code into a binary file boot.bat. Next, we write to the Java code that generates the virtual floppy disk the statements to be output to the virtual floppy 1 cylinders, 2 sectors, the code is as follows:
public void makeFllopy() { "This is a text from cylinder 1 and sector 2"; floppyDisk.writeFloppy(Floppy.MAGNETIC_HEAD.MAGNETIC12, s.getBytes()); floppyDisk.makeFloppy("system.img"); }
In the above code, we write the S string to the virtual floppy 0 heads, 1 cylinders, 2 sectors. Put the compiled boot.bat into the Java project directory, then run the Java code, after running the directory will generate a system.img virtual image, and then add the file as a startup floppy disk into the virtual machine:
Then start the virtual machine and you can see that our system kernel reads the string from the 1 cylinders of the floppy disk, 2 sectors, and displays it on the screen:
The code can be obtained according to the following GIT commands:
git clone https://github.com/wycl16514/OS-kernel-development.git
Operating system kernel with Java: Floppy disk read and write