org 7C00H				;bootloader
bits 16

mov di, 0				;move ds to zero
mov ds, di				

mov ah, 42H				;42h = read
mov si, diskthingy		;si is a pointer to diskythingy
int 13H					;call disk services

jc error_handler		;jump to the error handler if not successful (carry)

mov si, message			;print that the kernel has been loaded
call print
xor ax, ax
xor si, si
int 16H

jmp setup_protected_mode

error_handler:
	mov dh, ah			;save value of ah currently (ah gets overwritten by print)

	mov si, fail
	call print
	
	mov al, dh			;putting value of old ah into al		
	int 10H				;print
	hlt					;halt system

message db 'Kernel loaded. Press any key to continue...', 0
fail db 'Loading the kernel failed. Error code: ', 0 

print:
	mov ah, 0EH
	.loopc:				;a little improvised printing function
		mov al, [si]
		cmp al, 0
		je .endc
		int 10H
		inc si
		jmp .loopc
	.endc:
		ret

diskthingy:	db 16,0	
.read_sector: dw 8
.offset: dw 7e00h
.segment: dw 0000h
.end: dq 1H

gdt:					;GDT GUIDE !!!!!!!!
	dq 0				;64 bits null ('null descriptor' or whatever)
						;start of code descriptor (where we define our executable code, i guess...)
	dw 0FFFFH			;this is the max we can set our segment registers (so we can load highest potental value in there)
	dw 0				;this is the segment starting address (0), so we can access from 0 to FFFFH
	db 0				;continuation of last section (with segment starter address)
	db 10011010B		;MAGICAL TABLE!!!! ;;;;;;;KEY;;;;;;;; (bits go least -> most significance: 76543210)
						;bit 0 == 'access bit' (dont worry about it, something called 'virtual memory' or some bullshit)
						;bit 1 == 'read/write bit' (1 for read/execute, 0 is for just execute)
						;bit 2 == 'expansion direction' don't quite know what it does, leave to 0
						;bit 3 == 'code/data descriptor' (this is a code descriptor, so we set to 1)
						;bit 4 == 'system/(code or data)' (again, this is code, so it is a 1)
						;bit 5-6 == 'permissions level' (0 == kernel, 3 == apps)
						;bit 7 == again, virtual memory. don't really know/care.
	db 11001111B		;another key
						;bits 0-3 == 20th address line max value (for when we enable the address line)
						;bits 4-5 == reserved/we just dont give a fuck
						;bit 6 == 16 (0) or 32 (1) bit (we want 1, since that's why we are doing this in the first place -_____-)
						;bit 7 == 'granulaity', set to 1 for 4 kB for something to do with segments.... (i fucking hate segments)
	db 0				;last byte of starting address for segments that was before the two 'magical tables' (wtf is this ordering...)
						;data descriptor (or whatever)
	dw 0FFFFH			;same thing basically
	dw 0				
	db 0				
	db 10010010B		;except we set the code descriptor bit to zero, because data descriptor!
	db 11001111B		
	db 0
	
gdtp: 
	dw gdtp-gdt-1
	dd gdt
	
setup_protected_mode:
	mov ax, 03H			;setup VGA graphics mode for ease
	int 10H				
	
	in al, 92H			;enabling A20 gate via port 146
	or al, 2
	out 92H, al 
	
	cli					;disable interupts
	lgdt [gdtp]			;global descriptor table
	mov eax, cr0		;we need to set bit one of cr0 to enter protected
	or eax, 1			;so we set it in eax
	mov cr0, eax		;and move it back
	jmp 08H:clear		;far jump to clear all of the registers;
	bits 32
	
times 510-($-$$) db 0
dw 0AA55H						;END OF BOOTLOADER

	clear:
		mov ax, 10H
		mov ds, ax
		mov es, ax
		mov fs, ax
		mov gs, ax
		mov ss, ax
		mov esp, 90000H
		mov si, setup
		call print_str 
		;hlt
	
	start:
		;mov si, isr_handler
		;xor di,di
		;call load_idt_entry
		call load_isrs
		;mov si, end_idt
		;mov ecx, 256
		;call print_4_length
		;hlt
		;call set_irqs
		lidt [idtptr]				;loading idt
		;sti
		;hlt
		mov si, entry
		call print_str
		;int 3
		xor eax, eax
		div eax					;should raise the first exception
		hlt							;halt for now
	
	setup db 'Have not gotten past protected yet...', 0
	entry db 'Here we are again...', 0
	
	cur_line dd 000B8000H
	curx db 0
	
	print_str:
		mov edi, 0B8000H
		mov bx, curx
		.loop:
			mov al, byte [si]
			cmp al, 0
			je .end
			mov [edi], byte al
			mov [edi+1], byte 2AH
			inc si
			;mov eax, dword [di]
			;add eax, 2
			;mov [di], dword eax
			add edi, 2
			jmp .loop
		.end:
			ret
			
	print_4_length:
		mov edi, 0B8000H
		mov ebx, curx
		.loop:
			mov al, byte [esi]
			cmp esi, ecx
			je .end
			cmp al, 0
			je .mov0
			inc ecx
		.go:
			mov [edi], byte al
			mov [edi+1], byte 2AH
			inc esi
			;mov eax, dword [di]
			;add eax, 2
			;mov [di], dword eax
			add edi, 2
			jmp .loop
		.end:
			ret
		.mov0:
			mov al, ' '
			jmp .go
			
	
	load_idt_entry:			;esi == base, edi == number of entry in idt
		push edi
		push esi
		imul edi, 8			
		add edi, idt
		
		mov al, byte [esi+2]				
		mov [edi], byte al
		inc edi
		mov al, byte [esi+3]				
		mov [edi], byte al
		inc edi
		mov [edi], byte 0
		inc edi
		mov [edi], byte 08H
		inc edi
		mov [edi], byte 0
		inc edi
		mov [edi], byte 8EH
		inc edi
		mov al, byte [esi]				
		mov [edi], byte al
		inc edi
		mov al, byte [esi+1]
		mov [edi], byte al
		inc edi
		
		pop esi
		pop edi
		ret
		
	load_isrs:
		xor edi, edi
		mov esi, isr_handler
		.loop:
			cmp edi, 20H
			je .end
			call load_idt_entry
			inc edi
			jmp .loop
		.end:
			ret
	
	isr_1 db 'An exception occured. Processor halting. Sorry.',0
	
	isr_handler:
		cli
		pusha
		push ds
		push es
		push fs
		push gs
		mov si, isr_1
		call print_str
		hlt					;for now
		pop gs
		pop fs
		pop es
		pop ds
		popa
		add esp, 8
		sti
		iret	
	
	idtptr:
		dw end_idt-idt-1			;4 bytes per entry * 256 entries (256 interrupts) - 1 (just cause)
		dd idt
	
	idt times 2048 db 0
		
	end_idt

times 4096-($-$$) db 0