📄 setup.s
字号:
.code16
.globl _start
.equ GDT_ENTRIES,3
.equ GDT_ENTRY_SZ,8
.equ SEG1,1<<3
.equ SEG2,2<<3
# For 8259A PIC initialization
.equ ICW1, 0x11 # ICW1 - ICW4 needed, cascade mode, interval=8,
# edge triggered.
.equ ICW2_MASTER, 0x20 # put IRQs 0-7 at 0x20
.equ ICW2_SLAVE, 0x28 # put IRQs 8-15 at 0x28
.equ ICW3_MASTER, 0x04 # IR2 connected to slave
.equ ICW3_SLAVE, 0x02 # slave has id 2
.equ ICW4, 0x01
_start:
# TODO: change base address!!
movw $0x09a0, %ax
movw %ax, %ds # set DS
#movw $0x09e0, %ax
movw %ax, %es # set es
call screen_setup # for 80 x 25 screen mode
movw $msg1, %si
call prints # print message
# Find & load kernel image
# Reset Disk Controller
xorw %ax, %ax
xorw %dx, %dx
int $0x13
# we will find root directory entry from sector 0x12 to 0x20
# for convenience
movw $0x09e0, %ax
movw %ax, %es
load_loop:
incw block_num
cmpw $0x20, block_num
jne load_proceed
call loader_not_found
load_proceed:
xorw %bx, %bx
movw block_num, %ax
call read_block # read at 0x09e0:0000
scan_loop:
movw %bx, %di
movw $loader_name, %si
movw $11, %cx
cld
repe cmpsb # compare string
jcxz found_file
addw $32, %bx # root dir entry size
cmpw $0x200, %bx # sector size
jl scan_loop
jmp load_loop
found_file:
movw %es:26(%bx), %ax
addw $33, %ax
subw $2, %ax
movw %ax, ldr_block
movw %es:28(%bx), %ax
movw $0x200, %bx
xorw %dx, %dx
divw %bx
incw %ax
movw %ax, ldr_sects
movw $0x1000, %ax
movw %ax, %es
xorw %bx, %bx
#############################
# For DEBUG
# movw ldr_block, %ax
# call print_hex
# movw ldr_sects, %ax
# call print_hex
#############################
do_load: # loading kernel to 0x1000:0000
movw ldr_block, %ax
call read_block
decw ldr_sects
cmpw $0x00, ldr_sects
je loading_done
addw $0x200, %bx
incw ldr_block
jmp do_load
loading_done:
movw $0x3f2, %dx # kill driver motor
xorw %ax, %ax
outb %al, %dx
movw $msg2, %si
call prints
###############################
# kernel loading done
# now, setup A20, mem, IDT, GDT, PIC, etc...
###############################
# Enable A20 line, using whole memory in this system
call enable_A20
movw $msg3, %si
call prints
# Check memsize
call detect_mem
# DEBUG CODE
movw $mem_check_msg, %si
call prints
movw mem_size_kb, %ax
call print_dec
call print_end
# From now, we setting up idt & gdt
cli
lidt IDT_pointer
lgdt GDT_pointer
# Initialize interrupt controller
call init_PIC
# OK, now switching to protected mode !!
movw $0x01, %ax
lmsw %ax
movw $SEG2, %ax # DS for kernel: 0x10
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
movl $0x80000, %esp # stack top (using DS)
# jump to 32bit code
# how to jump to 32bit code ????
# In case of linux, uses hard coding method
# is gas supporting jmpi instructuin ??
.byte 0x66, 0xea # prefix + jmpi opcode
.word 0x0000 # entry point of kernel
.word 0x0001 # 0x10000
.word SEG1 # code segment for kernel
# Maybe NEVER REACHED...
# screen setup for 80 x 25 mode
screen_setup:
movw $0xb800, %ax
movw %ax, %es
xorw %di, %di
movw $0x1f20, %ax
movw $0x800, %cx
cld
rep stosw
movb $0x02, %ah
xorw %dx, %dx
xorw %bx, %bx
int $0x10
ret
# For using whole memory, enabling A20 line
enable_A20:
cli
call delay
movb $0xd1, %al
outb %al, $0x64
call delay
movb $0xdf, %al
outb %al, $0x60
call delay
sti
ret
# Linux uses this code.
delay:
jmp .done
.done: ret
# Checking Memory size using INT 0x15
# But, we can only detect 64MB using this way...
detect_mem:
xorw %ax, %ax
movb $0x88, %ah
int $0x15
addw $1024, %ax
movw %ax, mem_size_kb
ret
# Init PIC
# : initialize master and slave PIC.
init_PIC:
movb $ICW1, %al
outb %al, $0x20 # ICW1 to master
call delay
outb %al, $0xA0 # ICW1 to slave
call delay
movb $ICW2_MASTER, %al
outb %al, $0x21 # ICW2 to master
call delay
movb $ICW2_SLAVE, %al
outb %al, $0xA1 # ICW2 to slave
call delay
movb $ICW3_MASTER, %al
outb %al, $0x21 # ICW3 to master
call delay
movb $ICW3_SLAVE, %al
outb %al, $0xA1 # ICW3 to slave
call delay
movb $ICW4, %al
outb %al, $0x21 # ICW4 to master
call delay
outb %al, $0xA1 # ICW4 to slave
call delay
movb $0xff, %al # mask all ints in slave
outb %al, $0xA1 # OCW1 to slave
call delay
movb $0xfb, %al # mask all ints but 2 in master
outb %al, $0x21 # OCW1 to master
call delay
ret
# print string pointed by SI
prints:
movb (%si), %al
cmpb $0x00, %al
je print_end
movb $0x0e, %ah
xorw %bx, %bx
int $0x10
incw %si
jmp prints
print_end:
movb $0x0e, %ah
movb $0x0d, %al # CR
xorw %bx, %bx
int $0x10
movb $0x0a, %al # LF
int $0x10
ret
# FUNCTION FOR DEBUG
print_dec: # print number in %ax
movw $0x0a, %bx
call number_convert
ret
print_hex: # print number in %ax in hexa format.
pushw %ax
movw $hex_prefix, %si
call prints
popw %ax
movw $0x10, %bx
call number_convert
ret
number_convert:
movw $number_buf, %di
xorw %cx, %cx
lp1:
pushw %bx
xorw %dx, %dx
divw %bx
popw %bx
movw $number_array, %si
addw %dx, %si
movb (%si), %dl
movb %dl, (%di)
incw %cx
incw %di
cmpw $0x0000, %ax
jg lp1
lp2:
decw %di
movb (%di), %al
movb $0x0e, %ah
xorw %bx, %bx
int $0x10
loop lp2
ret
lba_to_chs:
pushw %bx
pushw %ax
movw $0x24, %bx # calc track number
xorw %dx, %dx
divw %bx
movb %al, cyl
popw %ax # restore lba block number
pushw %ax
movw $0x12, %bx # calc head number
xorw %dx, %dx
divw %bx
movw $0x02, %bx
xorw %dx, %dx
divw %bx
cmpw $0x00, %dx
jne head_1
xorw %dx, %dx
jmp get_sect
xorw %dx, %dx
head_1:
movb $1, head
get_sect:
movb %dl, head
popw %ax # restore lba block num
movw $0x12, %bx
xorw %dx, %dx
divw %bx
incb %dl
movb %dl, sect
popw %bx
ret
read_block: # block number in %AX
call lba_to_chs
movb cyl, %ch
movb sect, %cl
movb head, %dh
movb $0x00, %dl
movw $0x0201, %ax # read at ES:BX
int $0x13
ret
loader_not_found:
movw $ldr_error, %si
pr_loop:
lodsb
cmpb $0x00, %al
je pr_exit
movb $0x0e, %ah
xorw %bx, %bx
int $0x10
jmp pr_loop
pr_exit:
hlt
jmp pr_exit
ret
#######################################
# variables for kernel image loading
#######################################
loader_name:
.ascii "KERNEL IMG" # file name with 8.3 format
ldr_block:
.word 0x0000
ldr_sects:
.word 0x0000
ldr_error:
.asciz "kernel.img is not found... Please reboot."
sect:
.byte 0x00
cyl:
.byte 0x00
head:
.byte 0x00
block_num:
.word 0x0012
#########################################
# variables for print message
#########################################
number_array:
.ascii "0123456789ABCDEF"
hex_prefix:
.asciz "0x"
number_buf:
.fill 32,1,0
mem_check_msg:
.asciz "Total Memory size: "
mem_size_kb:
.word 0
msg1:
.asciz "Now loading the hos02 kernel image ..."
msg2:
.asciz "Loading done."
msg3:
.asciz "A20 Enabled"
##########################################
# GDT & IDT data
##########################################
.org 976
.align 8
.word 0,0,0,0
GDT:
# Descriptor 0 : NULL segment
.word 0
.word 0
.word 0
.word 0
# Descriptor 1 : Kernel code segment
.word 0xFFFF # bytes 0 and 1 of segment size
.word 0x0000 # bytes 0 and 1 of segment base address
.byte 0x00 # byte 2 of segment base address
.byte 0x9A # present, DPL=0, code exec-read
.byte 0xCF # 4kb graanularity, 32bit code
.byte 0x00 # byte 3 of segment base address
# Descriptor 2 : Kernel data and stack segment
.word 0xFFFF
.word 0x0000
.byte 0x00
.byte 0x92 # present, DPL=0, data read/write
.byte 0xCF
.byte 0x00
GDT_pointer:
.word GDT_ENTRIES * GDT_ENTRY_SZ # limit
.word 0x9A00 + GDT # base address
.word 0
.word 0 # padding
IDT_pointer:
.word 0
.word 0,0
.word 0 # padding
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -