In order to execute the C language main function in Linux, in order to jump from the assembly language environment to the C language, the CPU working mode is transformed from 16 bits to 32-bit mode (C is 32-bit), and the GDT and IDT are re-established. However, there is no content in the GDT and IDT, so memory addressing and interrupts are not possible, and then the GDT and IDT are initialized.
After entering the 32-bit mode, the register will also become a 32-bit register, the following assembly syntax and the previous Intel assembly is somewhat different, for the AT-T assembly, the difference is not to repeat.
head.sstartup_32://Reset Segment Register contents MOVL $0x10,%eaxmov%ax,%dsmov%ax,%esmov%ax,%fsmov%ax,%gs //Initialize stack pointer, near stack top pointer to bottom LSS _ STACK_START,%ESP //Build Idtcall setup_idt//build Gdtcall SETUP_GDT //Set up a good GDT and IDT after reset segment register MOVL $0x10,%eaxmov%ax,% Dsmov%ax,%esmov%ax,%fsmov%ax,%gslss _stack_start,%espxorl%eax,%eax //Check if A20 successfully opened 1:incl%EAXMOVL%eax, 0x000000cmpl%eax,0x100000je 1b //After checking the 8087 math coprocessor, start the In-memory page call CHECK_X87JMP after_page_tablesafter_page_tables: //The following is the parameter of the main function into the stack pushl $0pushl $0pushl $0PUSHL $L 6//The address of the main function into the stack PUSHL $_main //Start memory paging jmp setup_paging
The above push _main operation is important because after the RET instruction, the _main function address in the stack will be loaded into CS, and IP, and the parameters will be loaded into the corresponding registers, these operations will be completed after setup_paging
setup_paging://Pre-Initialize 5k memory MOVL $1024*5,%ecxxorl%eax,%eaxxorl%edi,%edicld;rep;stosl//assigns 0x0000 to 0x1000 + 7,7 means that 111 represents access rights, 0x1000 as the base address of the page, and then maps 0X2000,0X3000,0X4000MOVL $pg 0+7,_pg_dirmovl $pg 1+7,_pg_dir+4movl $pg 2+7,_ PG_DIR+8MOVL $pg 3+7,_pg_dir+12movl $pg 3+4092,%edimovl $0xfff007,%eax //The above code is actually the creation of a 4096-byte kernel page table, each byte can be addressed to a 4k page , so can address the space for 16mstd1:stoslsubl $0x1000,%eaxjge 1bxorl%eax,%eaxmovl%eax,%cr3movl%cr0,%eaxorl $0x80000000,%eaxmovl% EAX,%CR0 //call RET to start executing the main function ret
Here is a memory paging diagram, addressing the need to find the page table directory according to the Pg_dir address, find the PG page table in the page directory, and then find the corresponding page in the page table
The art of Linux kernel design-start executing the main function