一段存代码,没有任何注释,我也忘记了。功能是:初始化进入保护模式,检测内存,并分页,加载内核,跳转到kernel.bin执行kernel是elf格式的。
%include "pm.inc"
org 1000h
jmp start
sectnum dw 19
sectnum1 db 1
init_kernel_ofs dw 0000h
init_kernel_seg dw 8000h
FATOFS dw 0000h
FATSEG dw 9000h
fatnum dw 9
fatnumcount dw 1
fatentry dw 200h
filename db 'KERNEL BIN'
kernel_msg: db "Loading kernel"
nofound_msg: db "No kernel."
ready: db "Ready."
;descriptor limitl basel basem attrib baseh
; dw dw db dw db
gdt:
null_des: descriptor 0,0,0,0,0
code_des: descriptor 0ffffh,0,0,attrib_ce+attrib_32+atrrib_limit_4k,0
data_des: descriptor 0ffffh,0h,0h,attrib_drw+attrib_32+atrrib_limit_4k,0
video_des: descriptor 0ffffh,8000h,0bh,attrib_drw+attrib_32,0
page_dir_des: descriptor 4095,0000h,20h,attrib_drw,0
page_tbl_des: descriptor 1023,1000h,20h,attrib_drw+atrrib_limit_4k ,0h
gdt_len equ $-gdt
code_sel equ code_des-gdt
data_sel equ data_des-gdt
video_sel equ video_des-gdt
page_dir_sel equ page_dir_des-gdt
page_tbl_sel equ page_tbl_des-gdt
page_dir_base equ 200000h ; 页目录开始地址: 2M
page_tbl_base equ 201000h ; 页表开始地址: 2M + 4K
base_setup_phyaddr equ 90000h ;INITSEG 9000h INITOFS 1000h
base_kernel_phyaddr equ 80000h ;kernel offset
kernel_entry_phyaddr equ 000400h ;kernel entry
vgdtr: pdescriptor gdt_len-1,gdt+base_setup_phyaddr
stack:
times 1024 db 0
top_stack equ $+base_setup_phyaddr
count dw 0
mem_size dd 0
mem_buffer times 512 db 0
msg db "In protect mode!",0
page_msg db "After paging!",0
check_msg db "Checked ok!",0
check1_msg db "Checked fail!",0
finish_msg db "Checked finish!",0
ram_size_msg db "Ram size:"
ards: ;address range descriptor struture
dd 0 ;base addr low
dd 0 ;base addr high
dd 0 ;length low
dd 0 ;length high
dd 0 ;type
offset_msg equ msg+base_setup_phyaddr
offset_page_msg equ page_msg+base_setup_phyaddr
offset_count equ count+base_setup_phyaddr
offset_mem_buffer equ mem_buffer+base_setup_phyaddr
offset_check_msg equ check_msg+base_setup_phyaddr
offset_check1_msg equ check1_msg+base_setup_phyaddr
offset_finish_msg equ finish_msg+base_setup_phyaddr
offset_ards equ ards+base_setup_phyaddr
offset_mem_size equ mem_size+base_setup_phyaddr
offset_ram_size_msg equ ram_size_msg+base_setup_phyaddr
start:
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, ax
xor ax,ax
call read_mem_info ;放前面,奇怪放后面就不行了
xor ah, ah
xor dl, dl
int 13h
call load_kernel
call kill_motor
lgdt [vgdtr]
cli
call enable_a20
mov eax,cr0
or eax,1
mov cr0,eax
jmp dword code_sel:base_setup_phyaddr+virtual
enable_a20:
push ax
in al,92h
or al,2
out 92h,al
pop ax
ret
disable_a20:
push ax
in al,92h
and al,0fdh
out 92h,al
pop ax
ret
read_mem_info:
mov di,mem_buffer
mov ebx,0
rl:
mov eax,0E820h
mov ecx,20
mov edx,534D4150h
int 15h
jc faile
add di,20
inc word [count]
cmp ebx,0
jne rl
jmp ok
faile:
mov word [mem_size],0
jmp finish
ok:
finish:
ret
load_kernel:
push ax
push bx
push cx
push si
push di
mov cx,14
mov si,kernel_msg
call print16_string
nof:
mov ax,[sectnum]
;mov ax,21
cmp ax,32
ja fail
mov di,[FATOFS]
push ax
mov ax,[FATSEG]
mov es,ax
pop ax
call read_sect
call search_file
inc word [sectnum]
cmp ax,-1
je nof
;ax=file first sector
fatread:
push ax
mov es,[init_kernel_seg]
mov di,[init_kernel_ofs]
add ax,31
call read_sect
pop ax
add word[init_kernel_ofs],200h
mov bx,[init_kernel_ofs]
push ax
mov al,'.'
call print16_char
pop ax
call get_entry
cmp ax,0ff8h
jae fatreadend
jmp fatread
fatreadend:
call print16_newline
push si
mov cx,6
mov si,ready
call print16_string
pop si
jmp o
fail:
call print16_newline
mov cx,10
mov si,nofound_msg
call print16_string
o:
pop di
pop si
pop cx
pop bx
pop ax
ret
kill_motor:
push ax
push dx
mov dx,03f2h
mov al,0
out dx,al
pop dx
pop ax
ret
;es: di=地址 ds: si=filename ax->起始扇区号 ax=-1 没找到
search_file:
push bx
push cx
push si
cld
mov bx,di
goon:
mov di,bx
and di,0ffe0h
mov si,filename
mov cx,11
repz cmpsb
cmp cx,0
jz find
add bx,32
cmp bx,200h ;FATOFS+512byte one sector
jae nofind
jmp goon
find:
;print
add di,15
mov ax,[es:di]
;add ax,31
jmp endserch
nofind:
mov ax,-1
endserch:
pop si
pop cx
pop bx
ret
;sectornum/18 ch=Q>>1 cl=R+1 dh=Q&1
;ax=扇区号,sectnum1=扇区数 es:di=mem addr
read_sect:
push ax
push bx
push cx
push dx
push di
mov bh,18
div bh
mov ch,al
shr ch,1
and al,1
mov dh,al
inc ah
mov cl,ah
mov dl,00h
mov bx,di
readagine:
;mov bx,[init_kernel_ofs]
;mov es,[init_kernel_seg]
mov ah,02h
mov al,1
int 13h
jc readagine
pop di
pop dx
pop cx
pop bx
pop ax
ret
;ax=sector es:di=fat men addr
get_entry:
push bx
push cx
push dx
push es
push di
mov bx,3
mul bx
mov bx,2
div bx
a:
cmp ax,[fatentry] ;first time=200h
jbe next
mov es,[FATSEG]
mov di,[FATOFS]
push ax
mov ax,[fatnumcount]
cmp ax,9
ja endread ;fat 9 项
call read_sect
pop ax
inc word[fatnumcount]
add word[fatentry],200h
;200h
jmp a
next:
push ax
mov es,[FATSEG]
mov di,[FATOFS]
mov ax,[fatnumcount]
call read_sect
pop ax
add ax,200h
sub ax,[fatentry]
add di,ax
mov ax,[es:di]
cmp dx,0
je even1
mov cl,4
shr ax,cl
jmp endread
even1:
and ax,0fffh
endread:
;int 3h
pop di
pop es
pop dx
pop cx
pop bx
ret
print16_newline:
push ax
mov al,0dh
call print16_char
mov al,0ah
call print16_char
pop ax
ret
;al char
print16_char:
push ax
push bx
mov ah, 0eh
;mov al, '.'
mov bx,000ch
int 10h
pop bx
pop ax
ret
;si addr ,cx count ,dh row ,dl col
print16_string:
push ax
ps16:
mov al,[si]
call print16_char
inc si
loop ps16
pend16:
pop ax
ret
;-----------------------------------protect
bits 32
virtual:
mov ax,data_sel
mov ds,ax
mov ss,ax
mov es,ax
mov fs,ax
mov ax,video_sel
mov gs, ax
mov esp,0ff00h
xor esi,esi
mov dx,0400h
mov cx,16
mov esi,offset_msg
call print_string
call print_newline
mov cx,14
mov esi,offset_finish_msg
call print_string
call print_newline
mov cx,14
mov esi,offset_check_msg
call print_string
call print_newline
mov bx,[offset_count]
call print_bx
call print_newline
;call init8259a
call dump_mem
call print_newline
call setup_paging
mov cx,13
mov esi,offset_page_msg
call print_string
call mov_kernel
jmp code_sel:kernel_entry_phyaddr
mov_kernel:
push eax
push ecx
push edx
push esi
xor eax,eax
mov ax,[80000h+2ch] ;elf_heder ->e_phnum
mov esi,[80000h+1ch] ;elf_header->e_phoff
add esi,80000h
coniue:
mov edx,[esi] ;p_type
cmp edx,0
jz noload
push eax
push esi
mov ecx,[esi+16] ;p_filesz size
mov edi,[esi+8] ;p_vaddr des
mov esi,[esi+4] ;p_offset src
add esi,base_kernel_phyaddr
;call mem_cpy
cpy2:
cmp ecx,0
jle cpy1
mov eax,[esi]
mov [edi],eax
add edi,4
add esi,4
sub ecx,4
jmp cpy2
cpy1:
pop esi
pop eax
noload:
add esi,020h
dec eax
jnz coniue
pop esi
pop edx
pop ecx
pop eax
ret
;es:edi des ,ds:esi src ,ecx size
mem_cpy:
cpy12:
cmp ecx,0
jle cpy11
mov eax,[esi]
mov [edi],eax
add edi,4
add esi,4
sub ecx,4
jmp cpy12
cpy11:
ret
setup_paging:
push edx
xor edx,edx
mov eax,[offset_mem_size]
mov ebx,1024*4096
div ebx ;edx remainder eax
test edx,edx
jz no_remainder
inc eax
no_remainder:
mov ecx,eax
push eax
mov ax,page_dir_sel
mov es,ax
mov ecx,1024
xor edi,edi
xor eax,eax
mov eax,page_tbl_base|page_p|page_usu|page_rww
s1:
stosd
add eax,4096
loop s1
mov ax,page_tbl_sel
mov es,ax
pop eax
;mov ecx,1024*1024
mov ebx,1024
mul ebx
mov ecx,eax
xor edi,edi
xor eax,eax
mov eax,page_p|page_usu|page_rww
s2:
stosd
add eax,4096
loop s2
mov eax,page_dir_base
mov cr3,eax
mov eax,cr0
or eax,80000000h
mov cr0,eax
jmp short .3
.3:
nop
pop edx
ret
init8259a:
mov al,011h ;master icw1
out 20h,al
call io_delay
out 0a0h,al ;slaver icw1
call io_delay
mov al,020h ;irq0 0x20
out 21h,al ;master icw2
call io_delay
mov al,028h ;irq8 0x28
out 0a1h,al ;slaver icw2
call io_delay
mov al,004h ;ir2
out 021h,al ;master icw3
call io_delay
mov al,002h ;ir2
out 0a1h,al
call io_delay
mov al,01h
out 021h,al ;master icw4
call io_delay
;mov al, 11111110b ; 仅仅开启定时器中断
mov al,0ffh ;ocw1
out 021h,al
call io_delay
mov al,0ffh ;owc1
out 0a1h,al
call io_delay
ret
io_delay:
nop
nop
nop
nop
nop
nop
ret
;bx
print_bx:
rol bx,8
call print_bl
rol bx,8
call print_bl
ret
print_ebx:
push cx
mov cl,4
ee:
rol ebx,8
call print_bl
add dl,2
loop ee
pop cx
ret
;bl
print_bl:
push ax
push cx
push dx
mov ax,dx
mov ch,2
l22:
mov cl,4
rol bl,cl
mov dl,bl
and dl,0fh
add dl,30h
cmp dl,39h
jbe l11
add dl,7
l11:
push ax
mov ah,al
mov al,dl
mov dl,ah
call print_char
pop ax
inc al
dec ch
jnz l22
mov dx,ax
pop dx
pop cx
pop ax
ret
;dh,dl row,col
print_newline:
xor dl,dl
inc dh
ret
;al char ,gs video_sel ,dh row,dl col
print_char:
push eax
push ebx
push ecx
push edi
xor ebx,ebx
xor ecx,ecx
mov bl,dh
mov cl,dh
shl ebx,6
shl ecx,4
add ebx,ecx
xor ecx,ecx
mov cl,dl
add ebx,ecx
shl ebx,1
mov edi,ebx
mov ah, 07h
mov [gs:edi],ax
pop edi
pop ecx
pop ebx
pop eax
ret
;esi addr ,cx count ,dh row ,dl col
print_string:
push ax
ps:
mov al,[esi]
call print_char
inc dl
inc esi
loop ps
pend:
pop ax
ret
dump_mem: ;display mem info
push esi
push ebx
push ecx
mov esi,offset_mem_buffer
mov cx,[offset_count]
du:
mov ebx,[esi+4]
call print_ebx
inc dl
mov ebx,[esi]
call print_ebx
inc dl
mov ebx,[esi+12]
call print_ebx
inc dl
mov ebx,[esi+8]
call print_ebx
inc dl
mov ebx,[esi+16]
call print_ebx
call print_newline
cmp ebx,1
jne du1
push edx
mov edx,[esi]
add edx,[esi+8]
cmp edx,[offset_mem_size]
jb ld
mov [offset_mem_size],edx
mov edx,[esi]
mov [offset_ards],edx
mov edx,[esi+4]
mov [offset_ards+4],edx
mov edx,[esi+8]
mov [offset_ards+8],edx
mov edx,[esi+12]
mov [offset_ards+12],edx
mov edx,[esi+16]
mov [offset_ards+16],edx
ld:
pop edx
du1:
add esi,20
dec cx
jnz du
call print_newline
mov cx,5
mov esi,offset_ards
du2:
mov ebx,[esi]
call print_ebx
inc dl
add esi,4
loop du2
inc dl
call print_newline
mov cx,9
mov esi,offset_ram_size_msg
call print_string
mov ebx,[offset_mem_size]
call print_ebx
pop ecx
pop ebx
pop esi
ret
;初始化进入保护模式,检测内存,并分页,加载内核,跳转到kernel.bin执行kernel是elf格式的。