Jelly
QQ: 457283
Http: // blog.csdn.net/jznsmail
! Main functions completed by this program
! 1. bootsect. s starts from 0x7c00
! 2. copy yourself to 0x90000
! 3. Read the setup. s program from the disk's 2nd sector to 0x90200
! 4. Read the system at 0x10000.
! 5. Get the device Number of the root file system
! 6. Display Information
!
! Program Execution
! + --- + 0xa0000
! |
! |
! + --- +
! |
! |
! | S |
! |
! |
! + --- + 0x90200
! | B |
! + --- + 0x90000
! |
! |
! + --- +
! |
! |
! |
! |
! | K |
! |
! |
! |
! + --- + 0x10000
! |
! |
! |
! |
! + --- +
! | B |
! + --- + 0x7c00
! |
! + --- + 0x0000
! 1 2 3
! B-bootsect. s program
! S-setup. s program
! K-system module
!
! Sys_size is the number of clicks (16 bytes) to be loaded.
! 0x3000 is 0x30000 bytes = 196kb, more than enough for current
! Versions of Linux
!
! Size of the system module after compilation and Connection
Syssize = 0x3000
!
! Bootsect. S (c) 1991 Linus Torvalds
!
! Bootsect. S is loaded at 0x7c00 by the BIOS-startup routines, and moves
! The iself out of the way to address 0x90000, and jumps there.
!
! It then loads 'setup' directly after itself (0x90200), and the system
! At 0x10000, using BIOS interrupts.
!
! Note! Currently system is at most 8*65536 bytes long. This shoshould be no
! Problem, even in the future. I want to keep it simple. This 512 KB
! Kernel size shoshould be enough, especially as this doesn't contain
! Buffer cache as in minix
!
! The loader has been made as simple as possible, and continuos
! Read errors will result in a unbreakable loop. Reboot by hand. It
! Loads pretty fast by getting whole sectors at a time whenever possible.
! Defines 6 Global identifier code segments, data segments, starting and ending addresses of uninitialized data segments
. Globl begtext, begdata, begbss, endtext, enddata, endbss
! Code segment
. Text
Begtext:
! Data Segment
. Data
Begdata:
! Uninitialized data segment
. BSS
Begbss:
! Code segment
. Text
Setuplen = 4! NR of setup-sectors
! Number of sections of the setup program
Bootseg = 0x07c0! Original address of boot-sector
! Original Segment address of boot-sector
Initseg = 0x9000! We move boot here-out of the way
! Move boot-sector here
Setupseg = 0x9020! Setup starts here
! The setup program starts here.
Sysseg = 0x1000! System loaded at 0x10000 (65536 ).
! System Module loaded to 0x10000 (64 K)
ENDSEG = SYSSEG + SYSSIZE! Where to stop loading
! Segment address to stop loading
! ROOT_DEV: 0x000-same type of floppy as boot.
! 0x301-first partition on first drive etc
ROOT_DEV = 0x306! Device number, which indicates that the root file system is the first partition of the 2nd hard disks.
! Device No. = master device no. * 256 + sub-device No. (= (major <8) + minor)
! Master device number: 1-memory, 2-disk, 3-hard disk, 4-ttyx, 5-tty, 6-parallel port, 7-non-Named Pipe
! 0x300 = 3*256 + 0 1st Hard Disks
! 0x301 = 3*256 + 1 1st hard disks, 1st partitions
! 0x306 = 3*256 + 6 2nd hard disks, 1st partitions
Entry _ start! Program entry point
_ Start:
! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
MoV ax, # bootseg! Set the DS register of the Data Segment to 0x07c0.
MoV ds, ax
MoV ax, # initseg! Set the additional segment es register to 0x9000
MoV es, ax
MoV CX, #256! Move the value Cx = 256 characters = 512 bytes
Sub si, si! Source Address DS: SI = 0x07c0: 0x0000
Sub Di, Di! Target address es: di = 0x9000: 0x0000
Rep! Repeat until Cx = 0
Movw! Move one word
! The above code is used to move the bootsect itself from the position 0x07c00 to the position 0x90000, with a total of 512 bytes
Jmpi go, initseg! Indirect jump. initseg is the segment address to jump.
! The following code is executed from 0x90000
Go: mov ax, CS! Set ds, es, and SS to 0x9000. CS jumps to 0x9000.
MoV ds, ax
MoV es, ax
! Put stack at 0x9ff00 .! Point the stack pointer to 0x9ff00 (0x9000: 0xff00)
MoV SS, ax
MoV sp, #0xff00! Arbitrary value> & gt; 512
! Because 0x90000-0x90200 is placed with bootsect, 0x90200 is started with setup with approximately 4 Sectors
! Therefore, the stack pointer SP must point to the position of 0x200 + 0x200*4 + stack size.
! Load the setup-sectors directly after the bootblock.
! Note that 'els' is already set up.
! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
Load_setup:
MoV dx, #0x0000! Drive 0, head 0
! Drive 0, head 0
MoV CX, #0x0002! Sector 2, track 0
! Sector 2, track 0
MoV BX, #0x0200! Address = 512, in initseg
! Buffer offset. Es has been set to 0x9000 in the preceding code.
MoV ax, #0x0200 + setuplen! Service 2, NR of sectors
! Read 4 disk sectors to memory
Int 0x13! Read it
! Call interrupted
JNC OK _load_setup! OK-continue
! If the CF parameter is not set, the read is successful and the request jumps to OK _load_setup.
MoV dx, #0x0000! Reset drive and head
MoV ax, #0x0000! Reset the diskette
Int 0x13! Reset
J load_setup! Retry
! The above code is interrupted by using the BIOS int 0x13 and reads the setup module from the first sector of the disk.
! At 0x90200, four sectors are read in total. If an error occurs in reading, reset the drive and try again.
! Int 0x13
! Ah = 0x02 read disk sectors to memory Al = number of sectors to be read
! Ch = track (cylindrical) number low 8 bits Cl = start sector (0-5 bits), track number high 2 bits (6-7)
! DH = head number DL = drive number (if it is a hard disk location 7, you need to set it)
! ES: BX = point to data buffer. If an error occurs, the CF flag is set.
! The setup module is loaded successfully.
OK _load_setup:
! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
! Get disk drive parameters, specifically NR of sectors/track
MoV DL, #0x00! Set drive number to 0
MoV ax, #0x0800! Ah = 8 is get drive Parameters
Int 0x13! Call interrupted
MoV CH, #0x00
Seg cs! Indicates that the next statement is operated in the segment referred to by the CS segment register,
MoV sectors, CX! Save the number of sectors per track
MoV ax, # initseg
MoV es, ax! Because elasticsearch overwrites the elasticsearch value when reading disk parameters, rechange it here.
! The above Code reads disk drive parameters, especially the number of sectors
! Int 0x13
! Ah = 0x08 DL = drive letter (if it is a hard disk, set 7 to 1)
! Returned information:
! If CF is set incorrectly, Ah = Status Code
! Ah = 0, Al = 0 BL = drive type (AT/PS2)
! Ch = maximum track number low 8 Bcl = maximum number of sectors per track (bit 0-5), maximum track number high 2 bits (bit 6-7)
! DH = maximum number of cores DL = number of drives
! ES: di = disk parameter table
! Display Information 'loading system... carriage return newline' contains 24 characters
! Print some inane message
MoV ah, #0x03! Read cursor POS
Xor bh, BH! Read cursor position
Int 0x10
MoV CX, #24! A total of 24 characters
MoV BX, #0x0007! Page 0, attribute 7 (normal)
MoV bp, # msg1! Point to the string to be displayed
MoV ax, #0x1301! Write string, move cursor
Int 0x10! Write a string and move the cursor
! OK, we 've written the message, now
! The following code loads the system module to 0x10000:
! We want to load the system (at 0x10000)
MoV ax, # sysseg
MoV es, ax! Segment of 0x010000
Call read_it! Reads the system module. Es is the input parameter.
Call kill_motor! Turn off the drive motor
! After that we check which root-device to use. If the device is
! Defined (! = 0), nothing is done and the given device is used.
! Otherwise, either/dev/ps0 (2, 28) or/dev/at0 (2, 8), depending
! On the number of sectors that the BIOS reports currently.
! In Linux, the primary device Number of the soft drive is 2, and the secondary device number is = type * 4 + Nr. the NR value 0-3 corresponds to the drive A, B, C, and D types respectively.
! Soft drive type 2-1.2 m 7-1.44 m
! Because 7*4 + 0 = 28,/dev/ps0 (2, 28) refers to the 1.44 m a drive, and its device number is 0x21c
! Similarly,/dev/at0 (2, 8) indicates a 1.2 m a drive, and the device number is 0x0208.
SEG CS
MoV ax, root_dev! Get root device number
CMP ax, #0! If the value is not 0, the system will jump to root_defined to prove that the root device number has been specified.
JNE root_defined
! Check root device number
Seg cs! The following code is in the section specified by CS:
MoV BX, sectors! Get the number of sectors per track for a 10-1.2mb drive 18-1.44mb drive
MoV ax, #0x0208! /Dev/ps0-1.2 MB
Cmp bx, #15! Determine if the number of sectors per track is 15
Je root_defined! Is equal to, the device Number of the drive to which ax is directed
MoV ax, # 0x021c! /Dev/ps0-1.44 MB
Cmp bx, #18
Je root_defined
Undef_root :! If they are different, they will crash.
JMP undef_root
Root_defined:
SEG CS
MoV root_dev, ax! Save device number
! After that (everyting loaded), we jump
! The setup-routine loaded directly after
! The bootblock:
Jmpi 0, setupseg! Jump to 0x9020: 0000 (start of setup. s Program) and execute
! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! This program ends! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
! This routine loads the system at address 0x10000, making sure
! No 64kb boundaries are crossed. We try to load it as fast
! Possible, loading whole tracks whenever we can.
!
! In: Es-starting address segment (normally 0x1000)
!
Sread:. Word 1 + setuplen! Sectors Read of current track
! Number of read sectors in the current track, start to read the bootsect of one sector
Head:. Word 0! Current head
! Current head number
Track:. Word 0! Current track
! Current track number
Read_it:
MoV ax, es
Test ax, # 0x0fff! Compare the values in ES with 0x0fff to see if they are at 0x1000.
Die: JNE die! Es must be at 64kb boundary enters an endless loop if it is not at 0x1000
Xor bx, BX! BX is starting address within segment
! BX is the intra-segment offset address.
Rp_read:
MoV ax, es! Compare the Es value with endseg to check whether the segment ends. If not, the system jumps to okdomainread to continue reading. Otherwise, the system returns
CMP ax, # endseg! Have we loaded all yet?
JB ok1_read
RET
Okdomainread:
Seg cs! Set the following command to operate in the section specified by CS
MoV ax, sectors! Number of Sectors Read per track
Sub ax, sread! Number of read sectors deleted
MoV CX, ax! Cx = number of unread sectors
Shl cx, #9! Cx = Cx <9 = Cx * 512 bytes = Total number of bytes not read
Add CX, BX! Cx = cx + current offset in the segment determines whether the number of unread bytes + whether the offset in the segment exceeds 64kb
JNC ok2_read! 64 kB bytes not exceeded, jump to ok2_read to execute
Je ok2_read
! In the following case, the number of unread bytes + the intra-segment offset exceeds 64 KB.
XOR ax, ax! Clear ax
Sub ax, bx! Ax = ax-bx get the maximum number of bytes that can be read
Shr ax, #9! Convert to the number of sectors to be read
Ok2_read:
Call read_track
Mov cx, ax! Cx = number of sectors that have been read after the above call
Add ax, sread! Update the number of read sectors
Seg cs! The next command operation is in the CIDR Block specified by CS.
Cmp ax, sectors! If there are still sectors unread on the current track, jump to ok3_read
Jne ok3_read
Mov ax, #1! Determine the head number
Sub ax, head! If the value is 0, the sector data on the head is read again.
Jne ok4_read
Inc track! Otherwise, read the next track.
Ok4_read:
Mov head, ax! Save current head number
Xor ax, ax! Clear the number of read sectors of the current track
Ok3_read:
MoV sread, ax! Saves the number of read sectors of the current track
Shl cx, #9! Number of last read sectors x 512 bytes
Add Bx, CX! Adjust the start position of data in the current segment
JNC rp_read! If the value is smaller than 64 KB, the system jumps to rp_read to continue reading data.
MoV ax, es
Add ax, #0x1000! Adjust the segment base address to point to the start of the next 64 kB memory
MoV es, ax
Xor bx, BX! Offset in the clear segment
JMP rp_read! Jump to rp_read to continue execution
! Read data from the specified start sector and number of read sectors on the current track to the ES: BX
Read_track:
! Ax, BX, CX, DX such as stack
PUSH AX
Push BX
Push CX
Push DX
MoV dx, track! Obtain the current track number
MoV CX, sread! Obtains the number of read sectors on the current track.
Inc cx! CL = start read sector
MoV CH, DL! Ch = current track number
MoV dx, head! Number one of the current words
MoV DH, DL! DH = head number
MoV DL, #0! DL = drive letter (0 indicates the current drive)
And dx, #0x0100! The number one word cannot exceed 1
MoV ah, #2! Ah = 2, read disk sector function number
Int 0x13! Call interrupted
JC bad_rt! Error. Jump to bad_rt
Pop dx! Pop up dx, CX, BX, ax
Pop CX
Pop BX
Pop ax
RET
! Reset the drive (Disk interrupt feature no. 0) and redirect to read_track for retry.
Bad_rt: mov ax, #0
MoV dx, #0
Int 0x13
Pop DX
Pop CX
Pop BX
Pop ax
JMP read_track
! /*
! * This procedure turns off the floppy drive motor, so
! * That we enter the kernel in a known State, and
! * Don't have to worry about it later.
! */
Kill_motor:
Push DX
MoV dx, #0x3f2! The driver port of the soft drive control card. Only write
MoV Al, #0! Drive a, FDC off, static DMA and interrupt requests, motor off
Outb! Output Al content to the specified DX Port
Pop DX
RET
Sectors :! Used to store the number of track sectors
. Word 0
Msg1:
. Byte 13, 10! Carriage Return, line feed ASCII code
. ASCII "loading system ..."
. Byte 13, 10, 13, 10! A total of 24 ASCII characters
. Org 508! The following statement starts from 508 (0x1fc ).
Root_dev :! Save the device Number of the root file system (used by init/Main. c)
. Word root_dev
Boot_flag :! Valid hard disk ID
. Word 0xaa55
. Text
Endtext:
. Data
Enddata:
. BSS
Endbss: