⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 setup.s

📁 用于汇编领域的,运用于OS的MAIN函数.基于硬件基础的源代码
💻 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 + -