Linux-0.01 boot. s

Source: Internet
Author: User

The pilot part of the Linux-0.01 is mainly completed by two source code: boot. s and head. s. Boot. s is loaded and executed by the BIOS. head. s is a 32-bit boot code, and the main () function is called at the end to complete the system boot.

Boot. s code:

; Boot. s; boot. s is loaded at 0x7c00 by the bios-startup routines, and moves itself; out of the way to address 0x90000, and jumps there .;; it then loads the system at 0x10000, using BIOS interrupts. thereafter; it disables all interrupts, moves the system down to 0x0000, changes; to protected mode, and callthe start of system. system then must; RE-initialize the protected mode in it's own tables, And enable; interrupts as needed.; 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 shocould be enough-in fact more wowould mean we 'd have to move; not just these start-up routines, but also do something about the cache -; memory (block IO devices ). the area left over in the lower 640 kB is meant; for these. no other memory is assumed Be "physical", ie all memory; over 1 Mb is demand-paging. all addresses under 1 Mb are guaranteed to match; their physical addresses .;; NOTE1 abouve is no longer valid in it's entirety. cache-memory is allocated; abve the 1 Mb mark as well as below. otherwise it is mainly correct .;; NOTE 2! The boot disk type must be set at compile-time, by setting; the following equ. having the boot-up procedure hunt for the right; disk type is severe brain-damage .; the loader has been made as simple as possible (had to, to get it; in 512 bytes with the code to move to protected mode), and continuos; read errors will result in a unbreakable loop. reboot by hand. it; loads pretty fast by getting whol E sectors at a time whenever possible .; 1.44 Mb disks: sectors = 18; 1.2 Mb disks:; sectors = 15; kb disks:; sectors = 9. globl begtext, begdata, begbss, endtext, enddata, endbss. textbegtext :. databegdata :. bssbegbss :. textBOOTSEG = 0x07c0; INITSEG = 0x9000 address to which the Bootstrap program is loaded; SYSSEG = 0x1000, the target address to which the Bootstrap program moves itself; ENDSEG = SYSSEG + SYSSIZE; end address of the system code. SYSSIZE defines entry start in Makefile; program entry ID start: movax, # BOO TSEG; move the address loaded by the Bootstrap program to movds and AX in ax; set the base address of the Data Segment to movax, # INITSEG; set the target address mentioned above to moves and AX in ax; set the value in AX to ES, and use base address and offset to move the address movcx, #256; set the CX counter value to 256 subsi, si; clear SIsubdi, di; clear DIrep; Re-Execute movw 256 times, in fact, it is to put 512 K of data (the Bootstrap program itself) move to movw at INITSEG; move command, data addressing method, source: DS: SI, target: ES: DIjmpigo, INITSEG; jump command between jmpi segments, because the current code has been copied to INITSEG, it is in different segments. 64 K single segment go: movax, cs; move the code segment address to AXmovds, ax; move the AX value to DSmoves, ax; move the AX value to ESmovss, ax; move the value of AX to the SS. The base address of the stack segment is movsp, #0x400. The stack top pointer. The size of the stack segment is set to 512 KB. The stack may develop downward, otherwise it will overwrite the INITSEG code movah, #0x03; BIOS 10 H interrupted 03 H service, read the current cursor position, dh: Row, dl: column int0x10; execute 10 H to interrupt movcx, #24; Set CX value to 24, the number of characters needs to be displayed movbx, #0x0007; set display attribute; page 0, attribute 7 (normal) movbp, # msg1; load the starting address of the character to be displayed into BPmovax, #0x1301; 13 H display string (ES: BP = display string address) AL = display output mode (1: The string contains only the display characters, and its display attribute is in BL. After the display, the cursor position changes). The function is as follows: write a string to the screen and move the cursor int0x10; Execution interrupted; OK, we 've written the message, now; we want to load the system (at 0x10000) movax, # SYSSEG; set the value of AX to SYSSEGmoves and ax. Set the value of ES to SYSSEGcallread_it. call read_it. The call command uses the stack register callkill_motor. call kill_motor to disable the soft drive; if the read went well we get current cursor position and save it for; posterity. movah, #0x03; read cursor posxorbh, bhint0x10; save it in known place, con_init fetchesmov [510], dx; it from 0x90510. store the current cursor position to the last two bytes of the last segment of the system code; now we want to move to protected mode... cli; Disable interrupt; first we move the system to it's rightful placemovax, #0x0000; AX clears cld; DF is set to 0, and do_move: moves is added to SI and DI, ax; set the target code segment index: 0 addax, #0x1000; Add the code segment index to cmpax, #0x9000; compare the target code segment index with the end segment index to jzend_move; if it is equal, the copy is completed. Jump to end_movemovds, ax; source code segment subdi, di; DI when copying subsi, si; SI When resetting mov cx, #0x8000; repmovsw; move jdo_move in the form of word (16 bit); execute cyclically until the replication is complete; then we load the segment descriptorsend_move: movax, cs; after the system code is loaded, the code is still executed in the current segment. Because no data segment is used, the data is stored in the current segment. Therefore, you need to restore DS to the base address movds and ax of the current segment; set DS to correct tidt_48; load the Interrupt Descriptor Table load idt with 0, 0lgdtgdt_48; load the Global Descriptor Table load gdt with whatever appropriate; that was painless, now we enable A20Refer to Intel 8042 chip MaterialsCallempty_8042; call empty_8042moval, #0xD1; control code out #0x64, al; Output Control Code callempty_8042moval, # 0xDF; A20 onout #0x60, alcallempty_8042; well, that went OK, I hope. now we have to reprogram the interrupts:-(; we put them right after the intel-reserved hardware interrupts, at; int 0x20-0x2F. there they won't mess up anything. sadly IBM really; messed this up with the original PC, and they haven' t been able to; rectify it afterwards. thus the bios puts interrupts at 0x08-0x0f,; which is used for the internal hardware interrupts as well. we just; have to reprogram the 8259's, and it isn' t fun.Reference Intel 8259 Interrupt Controller Chip InformationMoval, #0x11; Initialization control code out #0x20, al; Output Control Code, send it to 8259A-1.word0x00eb, 0x00eb; jmp $ + 2, jmp $ + 2 machine code, because it is currently in the code segment, it will be executed. The delay function is out #0xA0, al; and to 8259A-2.word0x00eb, 0x00ebmoval, #0x20; start of hardware int's (0x20) out #0x21, al. word0x00eb, 0x00ebmoval, #0x28; start of hardware int's 2 (0x28) out #0xA1, al. word0x00eb, 0x00ebmoval, #0x04; 8259-1 is masterout #0x21, al. word0x00eb, 0x00ebmoval, #0x02; 8259-2 is slaveout #0xA1, al. word0x00eb, 0x00ebmoval, #0x01; 8086 mode for bothout #0x21, al. word0x00eb, 0x00ebout #0xA1, al. word0x00eb, 0x00ebmoval, # 0xFF; set the flag of the interrupt controller and disable all interrupted masks off all interrupts for nowout #0x21, al. word0x00eb, 0x00ebout #0xA1, al; well, that certainly wasn't fun :-(. hopefully it works, and we don't; need no steenking BIOS anyway (Bytes t for the initial loading :-).; the BIOS-routine wants lots of unnecessary data, and it's less; "interesting" anyway. this is how REAL programmers do it .;; well, now's the time to actually move into protected mode. to make; things as simple as possible, we do no register set-up or anything,; we let the gnu-compiled 32-bit programs do that. we just jump to; absolute address 0x00000, in 32-bit protected mode. movax, #0x0001; protected mode (PE) bitPE will be set to 1 and will enter the protection modeLmswax; lmsw indicates the state of the loaded machine, that is, the actual protection mode is entered.

After entering the protection mode, the segment register becomes the Selection Sub-, and the sub-structure is selected:
; 16 2 1 0
;---------------
; | Index | TI | RDL |
;---------------
Where TI = 0 is used to find the descriptor from GDT

Jmpi0, 8; jmp offset 0 of segment 8 (cs) Select child = 8 and jump to the descriptor with index number 1 in GDT, that is, the code segment. refer to the definition of GDT; this routine checks that the keyboard command queue is empty; No timeout is used-if this hangs there is something wrong with; the machine, and we probably couldn't proceed anyway. empty_8042:; 8042 is the keyboard controller. word0x00eb, 0x00ebinal, #0x64; read the status value of port #0x64 to AL, 8042 status porttestal, #2; test whether the second bit of AL is 1, is input buffer full? Jnzempty_8042; if the input buffer is not full, it is cyclically executed. If it is full, the function returns ret; This routine loads the system at address 0x10000, making sure; no 64kB boundaries are crossed. we try to load it as fast as; possible, loading whole tracks whenever we can .;; in: es-starting address segment (normally 0x1000 );Read process: first read one track, then read another disk surface of the same track, and then read the next track again.; This routine has to be recompiled to fit another drive type,; just change the "sectors" variable at the start of the file; (originally 18 for a 1.44 Mb drive );1.44 Mb Floppy Disk structure: 2-sided, 80-sided, 18-sector, 512-byte/sector, 2880-sector, 512-byte/sector, 2880-byte/sector X 1440-sector = KB, each track is 9 K and each segment is 64 K (7 tracks + 2 sectors). Pay attention to the overflow processing below.Sread :. word 1; number of sectors read by the current track head :. word 0; current head number track :. word 0; current track number read_it: mov ax, es; ES is the base address of the system code segment (ES will be added after the current segment is fully read) test ax, # 0x0fff; it is equivalent to 4-bit high erasing of AX, and 4-bit low maintaining the original value. 0x0FFF is 64die: jne die. It needs to be aligned by sector copying, xor bx, bx, and BX, used to mark the start address. After reading the data, the BX changes rp_read: mov ax, es; loads the ES value to the cmp AX, # ENDSEG; compare the value of AX with the end address to determine whether to load jb Okamoto read. If the value is smaller than # ENDSEG, jump to oksag readret. When the process ends, return, by redirecting to the return address stored in the stack, you can continue to execute okdomainread:; when data is not filled up to # ENDSEG, run mov ax, # sectors; load the number of sectors to AX, it is actually ALsub ax, sread; the value of AX is reduced by one, actually it is AL,When the following disk is read, AL indicates the number of sectors.Mov cx, ax; set the CX value to the value of AX,At this time, the number of last read sectors stored in AXShl cx, #9; the 9 power of 2 is 512, and the number of remaining sectors multiplied by 512 bytes equals to the number of read bytes add cx, bx; CX is a 16-bit register, up to 64 K data can be represented,Overflow is required if the number of read bytes plus the base address (BX) exceeds the current segmentJnc ok2_read; If CF is not set to a bit, it will jump, that is, it will continue execution without overflow. This indicates that if the data read is less than 64 K, je ok2_read will be executed; using the zero sign ZF for jump judgment conditions, this indicates that if the read data is equal to 64 K jump execution xor ax, ax;If the code is executed, the read overflow occurs. That is, the remaining bytes of the current track exceed the bytes required for the current segment.Sub ax, bx; overflow, equivalent to 0xFFFF-BX, equal to the number of bytes that need to be filled in shr ax, #9; AX/512; 512 bytes per sector, in this case, AX still needs to read the number of sectors.Ok2_read:; execute call read_track when the current segment is not filled; call read_trackmov cx, ax; Set CX to AX, which stores the number of sectors read last time add AX, sread; set the value of AX to AX + sread = Total Sectorscmp ax, # sectors; Determine whether jne ok3_read has been read; if not, jump to ok3_readmov ax, #1; set AX to 1 and run it here to indicate that the current track sector has been read by sub ax, head; AX = AX-headjne ok4_read; if it is not 0, the current disk has been read, jump to ok4_readinc track; if it is 0, the current disk is not completed, add the track number, continue to read the next track ok4_read:; when reading the current disk, execute mov head, ax; save the value of AX to xor ax and ax in the head; clear AX and execute ok3_read:; execute mov sread and ax when the current track has not been read; save the next track number to be read to sread shl cx, #9; multiply CX by 512, and CX represents the number of remaining read sectors, in this case, CX indicates the number of remaining read bytes add bx, cx; BX = BX + CX,At this time, BX is the starting address for storing data next time.Jnc rp_read; if it does not exceed 64 K, continue reading mov ax, es; if it exceeds 64 K, set the ES (Segment Base Address) value to add AX, #0x1000; AH plus mov es, ax; Set ES to AX, move to the next segment xor bx, bx; clear BXjmp rp_read; Continue to read the current track read_track:
The H function of BIOS 13 H: reads one or more slice content from the disk into the storage device. Because this is a low-level function, all the sectors read in one operation must be on the same track (the same head number and track number)
; Entry parameter: AH = 02 H; function number
; AL = number of sectors
CH, CL = the low 8-digit Magnetic Track number, the position 7-6 indicates the high 2-digit Magnetic Track number, and the low 6-digit indicates the start fan area number to be read.
; DH, DL = head number, drive number
; ES: BX = data buffer address
; Return: AH = 0: Successful, AL = number of read sectors;
If CF = 1, AX stores the error status AH = error code.
Note: The DS, BX, CX, and DX registers remain unchanged.
; Head number: disk A = 0; disk B = 1.
; Drive letter: Soft drive A = 0; soft drive B = 1; hard drive = 80 H
Push axpush bxpush cxpush dx; protect the site,At this time, AL is equal to the number of remaining read sectors. Note: In the following code, DX is used as a temporary data storage ELE. Me register.Mov dx, track; Set DX to track (track number), DL is the track number, DX is the temporary data mov cx, sread; set CX to sread.CL is the fan area numberInc cx; CX plus 1,The reason for adding one: the first sector (512 K) of the disk stores the boot code, not the system code. The system code starts from the second sector, except for the first read from 1.Mov ch, dl; Set CH to DL, that is, the track number.CH is the track number-the track number and the fan area number have been setMov dx, head; DX is set as the head number, here it is DL, then DL is the head number, DL is the temporary data mov dh, dl; DH is also set as the head number, in this case, DH is the head number mov dl, #0; DL is set to 0, and disk drive A = 0,DL is the drive letterAnd dx, #0x0100; values in DX except the last digit of DH are retained, and other values are cleared (can the above Code be removed ?),DH indicates the head number.Mov ah, #2; set AH to 2, function no. int 0x13; call BIOS 13 H to interrupt jc bad_rtpop dxpop cxpop bxpop ax; restore on-site retbad_rt: mov ax, # 0mov dx, # 0int 0x13; floppy disk reset, H of 13 H function -- floppy disk system reset, AH = 00 H function number, DL = drive letter, in short:ResettingPop dxpop cxpop bxpop axjmp read_track; jump to read_track, that is:If an exception occurs when reading the current sector, continue reading/** 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 dxmov dx, # 0x3f2mov al, #0 outbpop dxretgdt :. word0, 0, 0; dummy. word0x07FF; 8 Mb-limit = 2047 (2048*4096 = 8 Mb ). word0x0000; base address = 0. word0x9A00; code read/exec. word0x00C0; granular ity = 4096,386. word0x07FF; 8 Mb-limit = 2047 (2048*4096 = 8 Mb ). word0x0000; base address = 0. word0x9200; data read/write. word0x00C0; granularity = 4096,386 idt_48 :;. word0; idt limit = 0. word0, 0; idt base = 0Lgdt_48 :. word0x800; gdt limit = 2048,256 GDT entries. wordgdt, 0x9; gdt base = 0X9xxxxmsg1 :. byte 13, 10. ascii "Loading system... ". byte 13, 10, 13, 10. textendtext :. dataenddata :. bssendbss:

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.