1; This code runs in 16-bit Real Mode when the computer starts.
  2; It is responsible for loading the kernel and switching to 32-bit Protected Mode.
  3
  4[org 0x7c00]          ; BIOS loads the bootloader at this memory address
  5KERNEL_OFFSET equ 0x1000 ; Memory address where we will load our kernel
  6
  7; Save the boot drive index provided by BIOS in DL register
  8mov [BOOT_DRIVE], dl
  9
 10; Initialize the stack pointer to a safe area in memory
 11mov bp, 0x9000
 12mov sp, bp
 13
 14; Load the kernel from the disk into memory
 15call load_kernel
 16
 17; Switch to VGA Mode 13h: 320x200 resolution with 256 colors
 18; This is a graphical mode where each byte in video memory is a pixel color
 19mov ax, 0x0013
 20int 0x10
 21
 22; Enter 32-bit Protected Mode
 23call switch_to_pm
 24
 25; Infinite loop in case we ever return (we shouldn't)
 26jmp $
 27
 28; Global Descriptor Table (GDT)
 29; The GDT defines memory segments and their access rights for Protected Mode.
 30gdt_start:
 31	dd 0x0 ; The null descriptor is required at the beginning
 32	dd 0x0
 33
 34gdt_code:
 35	; Code segment descriptor
 36	dw 0xffff    ; Limit (bits 0-15)
 37	dw 0x0       ; Base (bits 0-15)
 38	db 0x0       ; Base (bits 16-23)
 39	db 10011010b ; Access byte: Present, Privilege 0, Code, Executable, Readable
 40	db 11001111b ; Flags: 4KB granularity, 32-bit mode, Limit (bits 16-19)
 41	db 0x0       ; Base (bits 24-31)
 42
 43gdt_data:
 44	; Data segment descriptor
 45	dw 0xffff    ; Limit (bits 0-15)
 46	dw 0x0       ; Base (bits 0-15)
 47	db 0x0       ; Base (bits 16-23)
 48	db 10010010b ; Access byte: Present, Privilege 0, Data, Writable
 49	db 11001111b ; Flags: 4KB granularity, 32-bit mode, Limit (bits 16-19)
 50	db 0x0       ; Base (bits 24-31)
 51
 52gdt_end:
 53
 54; The GDT descriptor is passed to the LGDT instruction
 55gdt_descriptor:
 56	dw gdt_end - gdt_start - 1 ; Size of GDT (minus 1)
 57	dd gdt_start               ; Starting address of GDT
 58
 59; Constants for segment selectors (offsets within the GDT)
 60CODE_SEG equ gdt_code - gdt_start
 61DATA_SEG equ gdt_data - gdt_start
 62
 63; Switch to 32-bit Protected Mode
 64[bits 16]
 65switch_to_pm:
 66	cli                     ; Disable interrupts while switching modes
 67	lgdt [gdt_descriptor]   ; Load the GDT descriptor
 68	mov eax, cr0            ; Enable Protected Mode bit in Control Register 0
 69	or eax, 0x1
 70	mov cr0, eax
 71	jmp CODE_SEG:init_pm    ; Far jump to flush the CPU pipeline and switch to 32-bit mode
 72
 73[bits 32]
 74init_pm:
 75	; Update all segment registers to use the new Data Segment selector
 76	mov ax, DATA_SEG
 77	mov ds, ax
 78	mov ss, ax
 79	mov es, ax
 80	mov fs, ax
 81	mov gs, ax
 82
 83	; Re-initialize the stack for 32-bit mode at a higher memory address
 84	mov ebp, 0x90000
 85	mov esp, ebp
 86
 87	; Call the entry point that leads to our kernel
 88	call BEGIN_PM
 89
 90; Routine to load sectors from disk using BIOS interrupts
 91[bits 16]
 92load_kernel:
 93	mov bx, KERNEL_OFFSET ; Destination address in memory
 94	mov dh, 15            ; Number of sectors to load (adjust if kernel grows)
 95	mov dl, [BOOT_DRIVE]  ; Drive index to read from
 96	call disk_load
 97	ret
 98
 99disk_load:
100	push dx
101	mov ah, 0x02 ; BIOS Read Sector function
102	mov al, dh   ; Number of sectors
103	mov ch, 0x00 ; Cylinder 0
104	mov dh, 0x00 ; Head 0
105	mov cl, 0x02 ; Sector 2 (Sector 1 is the bootloader)
106	int 0x13     ; Call BIOS disk interrupt
107	jc disk_error ; Jump if Carry Flag is set (indicates error)
108	pop dx
109	cmp dh, al    ; Verify that we read the expected number of sectors
110	jne disk_error
111	ret
112
113disk_error:
114	; Halt execution if disk read fails
115	jmp $
116
117; 32-bit entry point to jump into the compiled C kernel
118[bits 32]
119BEGIN_PM:
120	call KERNEL_OFFSET ; Jump to the memory location where kernel was loaded
121	jmp $              ; Safety hang
122
123; Boot sector padding and signature
124BOOT_DRIVE db 0
125times 510-($-$$) db 0 ; Pad the rest of the 512 bytes with zeros
126dw 0xaa55             ; The standard boot signature required by BIOS