这只是mpx386.asm文件的一部分内容,随着学习的深入我会把余下部分的注解也写下来。不过有一点很抱歉,我的这个注解主要是写给自己看,以免以后遗忘后无从下手。所以注解未免太个人化,不太容易懂。敬请谅解!
!在阅读这份代码之前,必须了解cpu的保护模式、GDT、LDT、IDT等相关概念。
.sect .text
!*===========================================================================*
!* MINIX *
!*===========================================================================*
MINIX: ! this is the entry point for the MINIX kernel
jmp over_flags ! skip over the next few bytes
.data2 CLICK_SHIFT ! for the monitor: memory granularity
flags:
.data2 0x01FD ! boot monitor flags:
! call in 386 mode, make bss, make stack,
! load high, don't patch, will return,
! uses generic INT, memory vector,
! new boot code return
nop ! extra byte to sync up disassembler
over_flags:

!在minix中将引导kernel也就是MINIX标签前的执行代码称之为mointor。
!The monitor sets CS to the kernel code, DS to kernel data, ES to a "flat
!4G" descriptor that address all memory simply from 0 up, and SS still
!points to the monitor's stack.

! Set up a C stack frame on the monitor stack. (The monitor sets cs and ds
! right. The ss descriptor still references the monitor data segment.)
movzx esp, sp ! monitor stack is a 16 bit stack
push ebp
mov ebp, esp
push esi
push edi
cmp 4(ebp), 0 ! monitor return vector is
jz noret ! nonzero if return possible
inc (_mon_return)
noret: mov (_mon_sp), esp ! save stack pointer for later return

! Copy the monitor global descriptor table to the address space of kernel and
! switch over to it. Prot_init() can then update it with immediate effect.

sgdt (_gdt+GDT_SELECTOR) ! get the monitor gdtr
mov esi, (_gdt+GDT_SELECTOR+2) ! absolute address of GDT
mov ebx, _gdt ! address of kernel GDT
mov ecx, 8*8 ! copying eight descriptors
!_gdt是位于kernel数据段内的GDT。
!GDT_SELECTOR(16bits)是GDT的段选择子,他的高13位是段描述符在GDT/LDT中的下标索引。
!sgdt读出gdtr寄存器到操作数地址,gdtr = 32bitsbaseAddr +16bitsLimit。
!(_gdt+GDT_SELECTOR+2) = gdt's baseAddr
copygdt:
eseg movb al, (esi) !esi保留的是monitor的GDT的偏移地址。它不位于kernel数据段内。所以es:si
!ES to a "flat 4G" descriptor that address all memory simply from 0 up
movb (ebx), al
inc esi
inc ebx
loop copygdt
mov eax, (_gdt+DS_SELECTOR+2) ! base of kernel data. _gdt+DS_SELECTOR+2 = 段基址的低24位
and eax, 0x00FFFFFF ! only 24 bits
add eax, _gdt ! eax = vir2phys(gdt)
mov (_gdt+GDT_SELECTOR+2), eax ! set base of GDT
lgdt (_gdt+GDT_SELECTOR) ! switch over to kernel GDT
!GDTR内是GDT的物理地址,而_gdt位于kernel的数据段内,所以
!kernel's GDTR = kernel数据段的基地址+_gdt偏移地址

! Locate boot parameters, set up kernel segment registers and stack.
mov ebx, 8(ebp) ! boot parameters offset
mov edx, 12(ebp) ! boot parameters length
mov eax, 16(ebp) ! address of a.out headers
mov (_aout), eax
mov ax, ds ! kernel data
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esp, k_stktop ! set sp to point to the top of kernel stack

! Call C startup code to set up a proper environment to run main().
push edx
push ebx
push SS_SELECTOR
push DS_SELECTOR
push CS_SELECTOR
call _cstart ! cstart(cs, ds, mds, parmoff, parmlen)
add esp, 5*4

! Reload gdtr, idtr and the segment registers to global descriptor table set
! up by prot_init().

lgdt (_gdt+GDT_SELECTOR)
lidt (_gdt+IDT_SELECTOR)

jmpf CS_SELECTOR:csinit
csinit:
o16 mov ax, DS_SELECTOR
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
o16 mov ax, TSS_SELECTOR ! no other TSS is used
ltr ax ! LTR指令是专门用于装载任务状态段寄存器TR的指令。
!该指令的操作数是对应TSS段描述符的选择子。LTR指令
!从GDT中取出相应的TSS段描述符,把TSS段描述符的基地址
!和界限等信息装入TR的高速缓冲寄存器中。
push 0 ! set flags to known good state
popf ! esp, clear nested task and int enable

jmp _main ! main()


posted on 2006-08-31 16:42 莫问春秋 阅读(1723)
评论(0) 编辑 收藏