InitKernel 自己动手写操作系统
转自:http://www.cnblogs.com/wanghj-dz/archive/2011/05/14/2046210.html
分析的很好
; InitKernel --------------------------------------------------------------------------------- bochs断点:0x000905ba
; 将 KERNEL.BIN 的内容经过整理对齐后放到新的位置
; 遍历每一个 Program Header,根据 Program Header 中的信息来确定把什么放进内存,放到什么位置,以及放多少。
; --------------------------------------------------------------------------------------------
InitKernel:
xor esi, esi
mov cx, word [BaseOfKernelFilePhyAddr+2Ch] ;`. ecx <- pELFHdr->e_phnum,把e_phnum=0x01赋给cx
movzx ecx, cx ;/
mov esi, [BaseOfKernelFilePhyAddr + 1Ch] ; esi <- pELFHdr->e_phoff,把e_phoff=0x34赋给esi
add esi, BaseOfKernelFilePhyAddr ;esi<-OffsetOfKernel+pELFHdr->e_phoff add esi,0x00080000,这样esi指向
.Begin: ; program header table
mov eax, [esi + 0] ;mov eax,01h.通过hex Editor打开kernel.bin发现在34位置的是01h,这表示段的类型
cmp eax, 0 ;为PT_LOAD 标记p_type为PT_LOAD的段,它表明了为运行程序而需要加载到内存的数据
jz .NoAction
push dword [esi + 010h] ;size ;`.把文件大小压入栈,作为第三个参数
mov eax, [esi + 04h] ; |;eax=0x00
add eax, BaseOfKernelFilePhyAddr ; | add eax,00080000h
push eax ;src ; | 源地址为00080000h压入栈,作为第二个参数
push dword [esi + 08h] ;dst ; | 把段的第一个字节在内存中的地址30000h压入栈,作为第一个参数
call MemCpy ; |MemCpy参数分别为:目的地址,源地址,个数。
add esp, 12 ;把用到的堆栈释放
.NoAction:
add esi, 020h ; esi指向下一个Program Header Entry程序头目录
dec ecx
jnz .Begin
ret
; InitKernel ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
jmp SelectorFlatC:KernelEntryPointPhyAddr ; 正式进入内核 * ,这个时候程序就跳到EFL格式的kernel.bin的真正代码处,从此控制权就由kernel接管
注:KERNEL 的位置实际上是很灵活的,可以通过同时改变 LOAD.INC 中的
; KernelEntryPointPhyAddr 和 MAKEFILE 中参数 -Ttext 的值来改变。
; 比如把 KernelEntryPointPhyAddr 和 -Ttext 的值都改为 0x400400,
; 则 KERNEL 就会被加载到内存 0x400000(4M) 处,入口在 0x400400。
;
;***************************************************************
; 内存看上去是这样的:
; ┃ ┃
; ┃ . ┃
; ┃ . ┃
; ┃ . ┃
; ┣━━━━━━━━━━━━━━━━━━┫
; ┃■■■■■■■■■■■■■■■■■■┃
; ┃■■■■■■Page Tables■■■■■■┃
; ┃■■■■■(大小由LOADER决定)■■■■┃
; 00101000h ┃■■■■■■■■■■■■■■■■■■┃ PageTblBase
; ┣━━━━━━━━━━━━━━━━━━┫
; ┃■■■■■■■■■■■■■■■■■■┃
; 00100000h ┃■■■■Page Directory Table■■■■┃ PageDirBase <- 1M
; ┣━━━━━━━━━━━━━━━━━━┫
; ┃□□□□□□□□□□□□□□□□□□┃
; F0000h ┃□□□□□□□System ROM□□□□□□┃
; ┣━━━━━━━━━━━━━━━━━━┫
; ┃□□□□□□□□□□□□□□□□□□┃
; E0000h ┃□□□□Expansion of system ROM □□┃
; ┣━━━━━━━━━━━━━━━━━━┫
; ┃□□□□□□□□□□□□□□□□□□┃
; C0000h ┃□□□Reserved for ROM expansion□□┃
; ┣━━━━━━━━━━━━━━━━━━┫
; ┃□□□□□□□□□□□□□□□□□□┃ B8000h ← gs
; A0000h ┃□□□Display adapter reserved□□□┃
; ┣━━━━━━━━━━━━━━━━━━┫
; ┃□□□□□□□□□□□□□□□□□□┃
; 9FC00h ┃□□extended BIOS data area (EBDA)□┃
; ┣━━━━━━━━━━━━━━━━━━┫
; ┃■■■■■■■■■■■■■■■■■■┃
; 90000h ┃■■■■■■■LOADER.BIN■■■■■■┃ somewhere in LOADER ← esp
; ┣━━━━━━━━━━━━━━━━━━┫
; ┃■■■■■■■■■■■■■■■■■■┃
; 80000h ┃■■■■■■■KERNEL.BIN■■■■■■┃
; ┣━━━━━━━━━━━━━━━━━━┫
; ┃■■■■■■■■■■■■■■■■■■┃
; 30000h ┃■■■■■■■■KERNEL■■■■■■■┃ 30400h ← KERNEL 入口 (KernelEntryPointPhyAddr)
; ┣━━━━━━━━━━━━━━━━━━┫
; ┃ ┃
; 7E00h ┃ F R E E ┃
; ┣━━━━━━━━━━━━━━━━━━┫
; ┃■■■■■■■■■■■■■■■■■■┃
; 7C00h ┃■■■■■■BOOT SECTOR■■■■■■┃
; ┣━━━━━━━━━━━━━━━━━━┫
; ┃ ┃
; 500h ┃ F R E E ┃
; ┣━━━━━━━━━━━━━━━━━━┫
; ┃□□□□□□□□□□□□□□□□□□┃
; 400h ┃□□□□ROM BIOS parameter area □□┃
; ┣━━━━━━━━━━━━━━━━━━┫
; ┃◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇┃
; 0h ┃◇◇◇◇◇◇Int Vectors◇◇◇◇◇◇┃
; ┗━━━━━━━━━━━━━━━━━━┛ ← cs, ds, es, fs, ss
;
;
; ┏━━━┓ ┏━━━┓
; ┃■■■┃ 我们使用 ┃□□□┃ 不能使用的内存
; ┗━━━┛ ┗━━━┛
; ┏━━━┓ ┏━━━┓
; ┃ ┃ 未使用空间 ┃◇◇◇┃ 可以覆盖的内存
; ┗━━━┛ ┗━━━┛