源**目錄src/sandnix/kernel/hal/init/arch
這部分幹的活可以歸為以下幾點
.global _start
.global gdt
.global kernel_header
.global tss_desc_table
.section .data
//gdt表
gdt:
segment_descriptor 0, 0, 0
descriptor_kernel_data:
segment_descriptor 0, 0xfffff, da_drw | da_dpl0 | da_32
descriptor_kernel_code:
segment_descriptor 0, 0xfffff, da_cr | da_dpl0 | da_32
descriptor_user_data:
segment_descriptor 0, 0xfffff, da_drw | da_dpl3 | da_32
descriptor_user_code:
segment_descriptor 0, 0xfffff, da_cr | da_dpl3 | da_32
tss_desc_table:
.rept max_cpu_num
segment_descriptor 0, 0x67, da_386tss | da_dpl0
.endr
gdt_end:
gdtr_value:
.word (gdt_end - gdt - 1)
gdt_addr:
.long gdt
.section .text
.align
8//描述核心映像資訊的結構體,編譯時由指令碼填充
kernel_header:
//magic
.long kernel_header_magic
//code_start
.long 0
//code_size
.long 0
//data_start
.long 0
//data_size
.long 0
//header_size
.long _kernel_header_end - kernel_header
//checksum
.long 0x100000000 - ((kernel_header_magic + (_kernel_header_end - kernel_header)) & 0xffffffff)
_kernel_header_end:
.long 0
/* step 1 : 檢查引導協議型別.咋檢查看multiboot2的文件 */
#if bootloader == multiboot2
//eax == magic.ebx = kernel parameters
_start:
cli//check bootloader
cmpl $0x36d76289, %eax
je _bootloader_checked
//if(eax != 0x36d76289)
_bootloader_checked:
//對的話就把引導資訊的位址壓棧
pushl %ebx
#endif
/* step 2 : 準備c的執行環境 */
//call/pop/sub組合計算偏移量,這招過去很多檔案型病毒也愛用
call _addr_1
_addr_1:
popl %eax
subl $_addr_1, %eax
//eax = offset
//write gdt address
movl $gdt, %edx
addl %eax, %edx
movl $gdt_addr, %ebx
addl %eax, %ebx
movl %edx, (%ebx)
//load gdt
movl $gdtr_value, %ebx
addl %eax, %ebx
lgdt (%ebx)
//load segments
movw $selector_u_data, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
//開分頁,這個函式是mmu模組提供的,用c寫的,訪問個全域性變數都要計算偏移,相當的蛋疼
call start_paging
//跳到核心空間,順便載入cs
ljmpl $selector_k_code, $_kernel_mem
_kernel_mem:
//reload stack
//彈出引導資訊
popl %edi
movl $init_stack, %ebx
addl $default_stack_size, %ebx
movl %ebx, %ebp
movl %ebx, %esp
//將剛才彈出的引導資訊壓棧,這樣正好作為核心主函式的引數
push %edi
//reload gdt
//write gdt address
movl $gdt, gdt_addr
//load gdt
movl $gdtr_value, %eax
lgdt (%eax)
//fpu
fninit
movl $0x80010021, %eax
movl %eax, %cr0
/* step 3 : call c code. */
//呼叫主函式
call kinit
.global _start
.global kernel_header
.section
.text
.align
8//跟上面一樣
kernel_header:
//magic
.long kernel_header_magic
//code_start
.long
0 //code_size
.long
0 //data_start
.long
0 //data_size
.long
0 //header_size
.long _kernel_header_end - kernel_header
//checksum
.long
0x100000000 - ((kernel_header_magic + (_kernel_header_end - kernel_header)) & 0xffffffff)
_kernel_header_end:
.long
0_start:
//保證處於svc模式並且遮蔽掉irq和fiq
ldr r5, =0x000000d3
msr spsr, r5
msr cpsr, r5
//計算偏移,原理和x86的一樣
_offchk_addr:
movr5, pc
subr5, r5, #8
ldr r6, =_offchk_addr
subr5, r5, r6 //r5 = offset
//載入核心棧
ldr sp, =init_stack
add sp, sp, r5
ldr r6,=default_stack_size
add sp, sp, r6
#if bootloader == uboot
//把引數壓棧
stmfd sp!,
#endif
//開分頁
bl start_paging
//重定位棧指標
sub sp, sp, r5
//把引數彈到r0
ldmfd sp!,
//呼叫主函式
ldr r1, =kinit
mov pc, r1
初始化 1 預設初始化 列表初始化
初始化的基本概念 事實 初始化和賦值是兩個完全不同的操作。初始化,是建立變數時賦予其乙個初始值。賦值,是把物件的當前值擦除,用乙個新值代替。列表初始化 p39 作為c 11新標準的一部分,用花括號 來初始化變數得到了全面應用。出於某些原因,這種初始化的方式叫做列表初始化。現在,無論是初始化物件還是某...
初始化 GDI 環境
初始化 gdi 環境我的開發環境為 vc.net 2003,下面我就來說一下在此開發環境中如何載入 gdi 開發環境,如果您的開發環境為 vc 6 請參考本文結尾部分。在標準的 mfc 開發環境中 mfc 是不支援 gdi 開發的,要想使用 gdi 需要我們手工對程式做一些修改。原理我就不想說了,感...
初始化GDI 環境
我的開發環境為 vc.net 2003,下面我就來說一下在此開發環境中如何載入 gdi 開發環境,如果您的開發環境為 vc 6 請參考本文結尾部分。在標準的 mfc 開發環境中 mfc 是不支援 gdi 開發的,要想使用 gdi 需要我們手工對程式做一些修改。原理我就不想說了,感興趣的朋友可以自己在...