📄 kernel.s
字号:
# Kinix kernel start
#
# Init some data & jmp to Protected Mode ...
# ... then call main()
#
# Author : Kasicass
# Date :
.text
.code16
.global start
start:
jmp begin16
#-----------------------------------------------------------------------------------------
# DATA
#-----------------------------------------------------------------------------------------
#
# Global descriptor table.
#
.p2align 4
gdt: .word 0x00, 0x00, 0x00, 0x00 # Null entry
gdt_code: # SEL_CODE (readonly, 0 - 4G)
.word 0xFFFF # Limit[15..0]
.word 0x0000 # Base[15..0]
.byte 0x00 # Base[23..16]
.byte 0x9A # 10011010b # P(1) DPL(00) S(1) 1 C(0) R(1) A(0)
.byte 0xCF # 11001111b # G(1) D(1) 0 0 Limit[19..16]
.byte 0x00 # Base[31..24]
gdt_data: # SEL_DATA (r/w, 0 - 4G)
.word 0xFFFF # Limit[15..0]
.word 0x0000 # Base[15..0]
.byte 0x00 # Base[23..16]
.byte 0x92 # 10010010b # P(1) DPL(00) S(1) 0 E(0) W(1) A(0)
.byte 0xCF # 11001111b # G(1) B(1) 0 0 Limit[19..16]
.byte 0x00 # Base[31..24]
gdt.1:
gdtdesc: .word gdt.1-gdt-1, gdt, 0
# gdt selector
.set SEL_CODE, gdt_code-gdt # 0x08
.set SEL_DATA, gdt_data-gdt # 0x10
#-----------------------------------------------------------------------------------------
# CODE 16
#-----------------------------------------------------------------------------------------
begin16:
cli
cld
movw %cs, %ax
movw %ax, %ds
movw %ax, %es
#
# prepare for protected mode
#
lgdt gdtdesc # set GDT
call seta20 # set A20
movl %cr0, %eax # switch to
orl $0x1, %eax # protected mode
movl %eax, %cr0 #
ljmp $SEL_CODE, $start32
#
# seta20 - Enable A20 so we can access memory above 1 meg.
# Inputs:
# None
# Outputs:
# None
# Modifies:
# %ax
#
# Note:
# This piece of code comes from FreeBSD
#
seta20:
# cli # Disable interrupts
seta20.1:
inb $0x64,%al # Get status
testb $0x2,%al # Busy?
jnz seta20.1 # Yes
movb $0xD1,%al # Command: Write
outb %al,$0x64 # output port
seta20.2:
inb $0x64,%al # Get status
testb $0x2,%al # Busy?
jnz seta20.2 # Yes
movb $0xDF,%al # Enable
outb %al,$0x60 # A20
# sti # Enable interrupts
ret # To callwer
#-----------------------------------------------------------------------------------------
# CODE 32
#-----------------------------------------------------------------------------------------
.code32
# 导入变量
.extern bss_start
.extern end
.extern idt_desc
# 导入函数
.extern OSCpuInit # init IDT, i8259A
.extern main # system start
.extern exception_handler
.extern irq_handler
# 导出函数
.global task_start
.global jump_into_task
.global divide_error
.global debug
.global nmi
.global breakpoint
.global overflow
.global bounds_check
.global inval_opcode
.global copr_not_available
.global double_fault
.global copr_seg_overrun
.global inval_tss
.global segment_not_present
.global stack_exception
.global general_protection
.global page_fault
.global intel_reserved
.global copr_error
.global alignment_check
.global machine_check
.global simd_fp_exception
.global hwint00
.global hwint01
.global hwint02
.global hwint03
.global hwint04
.global hwint05
.global hwint06
.global hwint07
.global hwint08
.global hwint09
.global hwint10
.global hwint11
.global hwint12
.global hwint13
.global hwint14
.global hwint15
# 代码开始
start32:
movw $SEL_DATA, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %ss
movw %ax, %gs
movl $0xA0000, %esp # stack pointer
#
# zero BSS
#
xorl %eax, %eax
movl $bss_start, %edi
movl $end, %ecx
subl %edi, %ecx
repnz
stosb
#
# system start
#
call OSCpuInit
lidt idt_desc
call main
# ud2
# sti
#
# die
#
die: jmp die
#
# 中断&异常 -- 异常
#
.p2align 4
divide_error: # "#DE Divide Error"
cli
pushl $0xFFFFFFFF # no error code
pushl $0 # vector_no = 0
jmp exception_common
debug: # "#DB Debug"
cli
pushl $0xFFFFFFFF # no error code
pushl $1 # vector_no = 1
jmp exception_common
nmi: # "-- NMI Interrupt"
cli
pushl $0xFFFFFFFF # no error code
pushl $2 # vector_no = 2
jmp exception_common
breakpoint: # "#BP Breakpoint"
cli
pushl $0xFFFFFFFF # no error code
pushl $3 # vector_no = 3
jmp exception_common
overflow: # "#OF Overflow"
cli
pushl $0xFFFFFFFF # no error code
pushl $4 # vector_no = 4
jmp exception_common
bounds_check: # "BR BOUND Range Exceeded"
cli
pushl $0xFFFFFFFF # no error code
pushl $5 # vector_no = 5
jmp exception_common
inval_opcode: # "#UD Invalid Opcode(Undefined Opcode)"
cli
pushl $0xFFFFFFFF # no error code
pushl $6 # vector_no = 6
jmp exception_common
copr_not_available: # "#NM Device Not Available(No Math Coprocessor)"
cli
pushl $0xFFFFFFFF # no error code
pushl $7 # vector_no = 7
jmp exception_common
double_fault: # "#DF Double Fault"
cli
pushl $8 # vector_no = 8
jmp exception_common
copr_seg_overrun: # "-- Coprocessor Segment Overrun(reserved)"
cli
pushl $0xFFFFFFFF # no error code
pushl $9 # vector_no = 9
jmp exception_common
inval_tss: # "#TS Invalid TSS"
cli
pushl $10 # vector_no = 10
jmp exception_common
segment_not_present: # "#NP Segment Not Present"
cli
pushl $11 # vector_no = 11
jmp exception_common
stack_exception: # "#SS Stack-Segment Fault"
cli
pushl $12 # vector_no = 12
jmp exception_common
general_protection: # "#GP General Protection"
cli
pushl $13 # vector_no = 13
jmp exception_common
page_fault: # "#PF Page Fault"
cli
pushl $14 # vector_no = 14
jmp exception_common
intel_reserved: # "-- (Intel reserved. Don't use.)"
cli
pushl $0xFFFFFFFF # no error code
pushl $15 # vector_no = 15
jmp exception_common
copr_error: # "#MF Floating-Point Error(Math Fault)"
cli
pushl $0xFFFFFFFF # no error code
pushl $16 # vector_no = 16
jmp exception_common
alignment_check: # "#AC Alignment Check"
cli
pushl $17 # vector_no = 17
jmp exception_common
machine_check: # "#MC Machine Check"
cli
pushl $0xFFFFFFFF # no error code
pushl $18 # vector_no = 18
jmp exception_common
simd_fp_exception: # "#XF Streaming SIMD Extensions"
cli
pushl $0xFFFFFFFF # no error code
pushl $19 # vector_no = 19
jmp exception_common
# common exception handler
exception_common:
call exception_handler
addl $8, %esp # 让栈顶指向 EIP,堆栈中从顶向下依次是:EIP、CS、EFLAGS
jmp die
# 中断&异常 -- 硬件中断
# ---------------------------------
.p2align 4
# master irq
.macro hwint_master irq
pushal
movb $0x20, %al # send EOI
outb %al, $0x20
pushl $\irq
call irq_handler
addl $4, %esp
popal
iret
.endm
hwing00: # Interrupt routine for irq 0 (the clock).
hwint_master 0
hwint01: # Interrupt routine for irq 1 (keyboard)
hwint_master 1
hwint02: # Interrupt routine for irq 2 (cascade!)
hwint_master 2
hwint03: # Interrupt routine for irq 3 (second serial)
hwint_master 3
hwint04: # Interrupt routine for irq 4 (first serial)
hwint_master 4
hwint05: # Interrupt routine for irq 5 (XT winchester)
hwint_master 5
hwint06: # Interrupt routine for irq 6 (floppy)
hwint_master 6
hwint07: # Interrupt routine for irq 7 (printer)
hwint_master 7
# slave irq
.macro hwint_slave irq
pushal
movb $0x20, %al # send EOI
outb %al, $0x20
pushl $\irq
call irq_handler
addl $4, %esp
popal
iret
.endm
hwint08: # Interrupt routine for irq 8 (realtime clock).
hwint_slave 8
hwint09: # Interrupt routine for irq 9 (irq 2 redirected)
hwint_slave 9
hwint10: # Interrupt routine for irq 10
hwint_slave 10
hwint11: # Interrupt routine for irq 11
hwint_slave 11
hwint12: # Interrupt routine for irq 12
hwint_slave 12
hwint13: # Interrupt routine for irq 13 (FPU exception)
hwint_slave 13
hwint14: # Interrupt routine for irq 14 (AT winchester)
hwint_slave 14
hwint15: # Interrupt routine for irq 15
hwint_slave 15
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -