Linux-0.01 Bootstrap code analysis-head. s

Source: Internet
Author: User
Tags prefetch

Head. s starts running by compiling the link and being loaded to the protection mode by boot. s. The main function is called at the end.

Code:

/** Head. s contains the 32-bit startup code. ** NOTE !!! Startup happens at absolute address 0x00000000, which is also where * the page directory will exist. the startup code will be overwritten by * the page directory. * Note: The Startup Program is 0x00000000 and the address is also the address of the page table. After the startup is complete, the program and data here will be overwritten by the page table. */. Code32. text. globl idt, gdt, pg_dir, startup_32pg_dir: startup_32: movl $0x10, % eax # already in 32-bit protection mode, $0x10 is the selection operator mov % ax, % dsmov % ax, % esmov % ax, % fsmov % ax, % gslss stack_start, % esp # set the system Stack: ss, esp,Stack_start is in kernel/sched. c, 40 rowsCall setup_idt # Set the Interrupt Descriptor Table call setup_gdt # Set the Global Descriptor Table # Because gdt is modified, all segment registers movl $0x10 need to be reloaded, % eax # reload all the segment registersmov % ax, % ds # after changing gdt. CS was alreadymov % ax, % es # reloaded in 'setup _ gdt 'mov % ax, % fsmov % ax, % gslss stack_start, % espxorl % eax, % eax # test whether the A20 address line is enabled. If not, the kernel cannot use memory larger than 1 MB. # The method is to write any value to the memory address 0x000000, # Check whether 0x100000 (1 M) is the same value. 1: incl % eax # check that A20 really IS enabledmovl % eax, 0x000000cmpl % eax, 0x100000je 1b # search for the label # CR0: http://en.wikipedia.org/wiki/Control_registermovl % cr0, % eax # check math chipandl $0x80000011, % eax # Save PG, ET, PEtestl $0x10, % eax # test MP bit jne 1f # ET is set-387 is presentorl $4, % eax # else set emulate bit, EM bit 1: movl % eax, % cr0jmp after_page_tables/********************************* setup_idt ** *** * ************************ // ** Setup_idt ** sets up a idt with 256 entries pointing to * ignore_int, interrupt gates. it then loads * idt. everything that wants to install itself * in the idt-table may do so themselves. interrupts * are enabled elsewhere, when we can be relatively * sure everything is OK. this routine will be over-* written by the page tables. * // ** the following section sets the Interrupt Descriptor Table subroutine setup_idt. ** Set the idt of the Interrupt Descriptor Table to have 256 Items and point to the ignore_int interrupt gate. Then load the interrupt * Descriptor Table register (using the lidt command ). Install the service after a real and practical disconnection door. Enable the interrupt when we think everything is normal elsewhere. This subroutine will be overwritten by the page table. */Setup_idt: lea ignore_int, % edx # Save the valid address (offset value) of ignore_int to the edx register movl $0x00080000, % eax # Place the selector 0x0008 in the high 16-bit position of eax movw % dx, % ax/* selector = 0x0008 = cs # The low 16 position of the Offset Value is included in the low 16 bits of eax. In this case, eax contains a four-byte value */movw $0x8E00, % dx/* interrupt gate-dpl = 0, present */lea idt, % edi # Save the valid idt address to edimov $256, % ecx #256,256 table items rp_sidt: movl % eax, (% edi) # store the eax value to the first 32-bit movl % edx, 4 (% edi) of the first item of idt) # store the edx value to the second 32-bit addl $8 in the first item of idt, % edi # point edi to the second idt item dec % ecxjne rp_sidt # repeat lidt idt_descr # Set the Interrupt Descriptor Table ret /************** * ***************** setup_gdt ******************** ***********//** Setup_gdt ** This routines sets up a new gdt and loads it. * Only two entries are currently built, the same * ones that were built in init. s. the routine * is VERY complicated at two whole lines, so this * rather long comment is certainly needed :-). * This routine will beoverwritten by the page tables. */setup_gdt: lgdt gdt_descr # set the global description of the appendix ret /******************************* ********************** * *************** // Linus directly places the kernel memory page table after the page Directory, two tables are used to address 8 Mb physical memory. * If you have more than 8 Mb memory, you need to modify it here. */# Each page table is 4 Kb in length, and each page table item needs 4 bytes. Therefore, a page table can store 1000 table items, # If a table item addresses 4 Kb of address space, a page table can address 4 Mb of physical memory. # The format of the page table item is: the first 0-11 bits of the item store some flags, such as whether it is in memory (P-Bit 0), read/write permission (R/W-bit 1) # normal users or Super Users (U/S bits 2), whether modified (dirty) (D bits 6), and so on; 12-31 is the # page box address, which is used to indicate the physical start address of a page of memory. # There are 1000 page tables starting from 0 x 1st offset (the page table directory will be stored at the beginning of 0 offset ). /*******************************0x1000 ***** **************************/. org 0x1000 # Set the starting address pg0: /*******************************0x2000 ***** **************************/. org 0x2000pg1: /*******************************0x3000 ***** **************************/. org 0x3000pg2: # This is not used yet, but if you # want to expand past 8 Mb, you'll have # to use it. /*******************************0x4000 ***** * *************************/. Org 0x4000after_page_tables: pushl $0 # These are the parameters to main :-) pushl $0 pushl $0 pushl $ L6 # return address for main, if it decides. pushl $ mainjmp setup_paging # code for page Jump setting L6: jmp L6 # main shoshould never return here, but # just in case, we know what happens. /********************************* default interrupt "handler "* ***************************** // This is Default interrupt "handler ":-)*/. align 2 #2-byte alignore_int: incb 0xb8000 + 160 # put something on the screenmovb $2, 0xb8000 + 161 # so that we know somethingiret # happened /**************************** * ***** Setup_paging *******************************//* * Setup_paging ** This routine sets up paging by setting the page bit * in cr0. The page tables are set up, identity-mapping * the first 8 MB. the pager Assumes that no illegal * addresses are produced (ie> 4 Mb on a 4 Mb machine). ** NOTE! Although all physical memory shoshould be identity * mapped by this routine, only the kernel page functions * use the> 1 Mb addresses directly. all "normal" functions * use just the lower 1 Mb, or the local data space, which * will be mapped to some other place-mm keeps track of * that. ** For those with more memory than 8 Mb-tough luck. I 've * not got it, why shoshould you :-) The source is here. ch Ange * it. (Seriously-it shouldn't be too difficult. mostly * change some constants etc. I left it at 8 Mb, as my machine * even cannot be extended past that (OK, but it was cheap :-) * I 've tried to show which constants to change by having * some kind of marker at them (search for "8 Mb "), but I * won't guarantee that's all:-() * // ** This subroutine sets the flag of the control register cr0 (PG bit 31) to enable the paging processing function for the memory, * and set the content of each page table item The first 8 MB physical memory of the constant ing. The page splitter does not generate an illegal * address ing (that is, a memory address greater than 4 Mb is set on a 4 Mb machine ). * Note! Although all physical addresses should be mapped by this subroutine, only the kernel page management function can directly use the address larger than 1 Mb. All "general" functions only use address space less than 1 Mb, or use local data * space, the address space will be mapped to other places -- mm (Memory Management Program) will manage these things. * For those guys with more than 8 Mb of memory-I am so lucky that I haven't. Why do you have it? The code is here, * modify it. (In fact, this is not too difficult. Generally, you only need to modify some constants. I set it to * 8 Mb, because how can I expand my machine to exceed this limit (of course, my machine is cheap ). * I have already set a certain flag to show the location to be changed (search for "8 Mb"), but I cannot guarantee to make these * changes ). */# Paging: http://en.wikipedia.org/wiki/Paging.align 2setup_paging: movl $1024*3, % ecx #0x1000 = 4096 byte = 1024*32 bits, pg2 is not used, nor is it initialized here. Xorl % eax, % eax # eax clear xorl % edi, % edi # edi clear/* pg_dir is at 0x000 */cld; rep; stosl # cld sets the transfer direction, rep repeats ecx times, and stos transfers the eax value to the memory pointed to by edi # The following two statements set items in the page Directory. We have two page tables, so we only need to set two items. # The structure of the page Directory items is the same as that of the items in the page table. The four bytes are one item. # "$ Pg0 + 7" indicates 0x00001007, which is the first item in the page Directory table. # The address of the 1st page tables = 0x00001007 & 0xfffff000 = 0x1000; # The attribute flag of the 1st page tables = 0x00001007 & 0x00000fff = 0x07, indicates that the page exists and the user can read and write. Movl $ pg0 + 7, pg_dir/* set present bit/user r/w */movl $ pg1 + 7, pg_dir + 4/* --------- "" --------- */# Fill in the content of all the items in the two page tables in the following six rows, total: 2 (page table) * 1024 (item/page table) = 2048 items (0-0 xfff), # ing physical memory 2048*4 kb = 8 Mb. # The content of each item is: the physical memory address mapped to the current item + the flag of this page (7 in this example ). # The method is to enter the last entry of the last page table in descending order. The # position of the last entry in the page table is 1023*4 = 4092. Therefore, the last item on the last page is $ pg3 + 4092. Movl $ pg1 + 4092, % edi # the address of the physical memory page corresponding to the last item is 0x7ff000, # Add attribute mark 7, that is, 0xfff007. movl $0x7ff007, % eax/* 8 Mb-4096 + 7 (r/w user, p) */std # direction position, edi value decreasing (4 bytes ). 1: stosl/* fill pages backwards-more efficient :-) */subl $0x1000, % eax # each fill in one item, the physical address value minus 0x1000. Jge 1b # If it is greater than or equal to zero, jump to 1 to continue execution. Xorl % eax, % eax/* pg_dir is at 0x0000 */# movl % eax at 0x0000, % Convention 3/* Convention-page directory start */# set to start paging processing (PG flag of cr0, bit 31) movl % cr0, % eaxorl $0x80000000, % eax movl % eax, % cr0/* set paging (PG) bit */# Add the PG flag # Use the transfer instruction to refresh the prefetch instruction queue after the pagination flag is changed, the returned command ret is used here. # Another function of the returned command is to pop up the address of the main program in the stack and start running the/init/main. c program. # This program has really ended. Finally, the end of the damn assembly code! Ret/* this also flushes prefetch-queue *//**************************** * ***** idt_descr *******************************/. align 2. word 0idt_descr :. word 256*8-1 # idt contains 256 entries. long idt/********************************* gdt_descr *** ****************************/. align 2. word 0gdt_descr :. word 256*8-1 # so does gdt (not that's any. long gdt # magic number, but it works for me: ^ )/**************** * **************** Idt ********************** *********/. align 8idt :. fill 256, 0 # idt is uninitialized #, 8 bytes for each item, fill in 0. /********************************** Gdt ***** * *************************/gdt :. quactive 0x0000000000000000/* NULL descriptor */. quad 0x00c09a00000007ff/* 8 Mb, code segment */. quad 0x00c09200000007ff/* 8 Mb, data segment */. quactive 0x0000000000000000/* TEMPORARY-don't use */. fill 252,8, 0/* space for LDT's and TSS's etc */
Further improvement is required.

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.