Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- [BITS 16]
- [org 0x8000]
- TSS_ADDR_HI_BYTE_OFFSET equ 5
- TSS_ACCESS_BYTE_OFFSET equ 7
- jmp a20_enter
- ; -------------------------
- ; Messages
- ; -------------------------
- section .data
- msg_a20_loading db 'A20 loading... ', 0x0D, 0x0A, 0
- msg_a20_error db 'A20 line enable -> failed ', 0x0D, 0x0A, 0
- msg_a20_enable db 'A20 line enable -> successfully ', 0x0D, 0x0A, 0
- msg_gdt_loading db 'GDT loading... ', 0x0D, 0x0A, 0
- msg_gdt_success db 'GDT load -> successfully ', 0x0D, 0x0A, 0
- msg_tss_loading db 'TSS loading... ', 0x0D, 0x0A, 0
- msg_tss_success db 'TSS load -> successfully ', 0x0D, 0x0A, 0
- ; -------------------------
- ; BSS Section for TSS
- ; -------------------------
- section .bss
- tss resb 104 ; Reserve 104 bytes for the TSS (Task State Segment)
- ; -------------------------
- ; Initialize the TSS
- ; -------------------------
- section .text
- init_tss:
- ; Set ESP0 (stack pointer for privilege level 0)
- mov eax, 0x9FC00 ; Example stack pointer for ring 0
- mov [tss + 4], eax ; Set ESP0 in the TSS
- ; Set SS0 (stack segment for privilege level 0)
- mov ax, 0x10 ; Kernel data segment selector (0x10)
- mov [tss + 8], ax ; Set SS0 in the TSS
- ; Swap the byte with tss address bits 24:31 with the access byte
- ; In the TSS descriptor
- mov al, [gdt.tss + TSS_ADDR_HI_BYTE_OFFSET]
- xchg al, [gdt.tss + TSS_ACCESS_BYTE_OFFSET]
- mov [gdt.tss + TSS_ADDR_HI_BYTE_OFFSET], al
- ret ; Return to the main flow
- ; -------------------------
- ; Print Message: A20 Loading
- ; -------------------------
- a20_enter:
- mov ax, 0x0000 ; Set data segment to 0 for memory access
- mov ds, ax
- mov ah, 0x0E ; BIOS teletype function (interrupt 0x10, AH=0x0E) for printing characters
- mov bh, 0x00 ; Display page number
- mov si, msg_a20_loading ; Load pointer to "A20 loading..." message into SI
- a20_print_loading:
- lodsb ; Load next byte from [SI] into AL
- cmp al, 0 ; Check if null terminator (end of string)
- je a20_status_check ; Jump to A20 status check if end of message
- int 0x10 ; BIOS interrupt to print character in AL
- jmp a20_print_loading ; Repeat for next character
- ; -------------------------
- ; A20 Status Check
- ; -------------------------
- a20_status_check:
- pushf ; Save flags
- push ds ; Save data segment
- push es ; Save extra segment
- push di ; Save destination index
- push si ; Save source index
- cli ; Disable interrupts during A20 check
- xor ax, ax ; Set AX to 0
- mov es, ax ; Set extra segment (ES) to 0
- mov di, 0x0500 ; Set DI to test memory location 0x0500 in low memory
- not ax ; Set AX to 0xFFFF (inverted 0)
- mov ds, ax ; Set data segment (DS) to 0xFFFF
- mov si, 0x0510 ; Set SI to memory location 0x0510 (also in low memory)
- ; Save original values from memory locations
- mov al, byte [es:di] ; Load byte at ES:DI into AL
- push ax ; Save value from ES:DI
- mov al, byte [ds:si] ; Load byte at DS:SI into AL
- push ax ; Save value from DS:SI
- ; Modify memory locations for the test
- mov byte [es:di], 0x00 ; Set ES:DI to 0x00
- mov byte [ds:si], 0xFF ; Set DS:SI to 0xFF
- ; Check if memory write is visible at ES:DI
- cmp byte [es:di], 0xFF ; Compare ES:DI with 0xFF
- ; Restore original memory values
- pop ax ; Restore value from stack to AX
- mov byte [ds:si], al ; Restore original byte at DS:SI
- pop ax ; Restore value from stack to AX
- mov byte [es:di], al ; Restore original byte at ES:DI
- ; Determine A20 status based on comparison result
- mov ax, 0 ; Assume A20 is off
- je status_a20_off ; Jump if A20 is off
- mov ax, 1 ; A20 is on
- jmp status_a20_on ; Jump to A20 enabled handling
- ; -------------------------
- ; A20 Enable via BIOS Interrupt 15h
- ; -------------------------
- status_a20_off:
- mov ax, 0x2401 ; Request to enable A20 via BIOS (INT 15h)
- int 0x15 ; BIOS interrupt call
- jc a20_error ; If carry flag is set (error), jump to error handler
- jmp a20_status_check ; Otherwise, recheck A20 status after enabling
- ; -------------------------
- ; A20 Enable Failure Handling
- ; -------------------------
- a20_error:
- mov ax, 0x0000 ; Reset segment register for message output
- mov ds, ax
- mov ah, 0x0E ; Set up for character output
- mov bh, 0x00 ; Display page number
- mov si, msg_a20_error ; Load error message into SI
- print_error_loop:
- lodsb ; Load next byte from message
- cmp al, 0 ; Check for null terminator
- je end_error_msg_a20 ; If end of string, stop printing
- int 0x10 ; Print character in AL
- jmp print_error_loop ; Loop to print the next character
- end_error_msg_a20:
- cli ; Disable interrupts
- hlt ; Halt the system
- ; -------------------------
- ; A20 Enable Success Handling
- ; -------------------------
- status_a20_on:
- mov ax, 0x0000 ; Reset data segment for message output
- mov ds, ax
- mov ah, 0x0E ; Set up for character output
- mov bh, 0x00 ; Display page number
- mov si, msg_a20_enable ; Load success message into SI
- print_enable_loop:
- lodsb ; Load next byte from message
- cmp al, 0 ; Check for null terminator
- je restore_registers_a20 ; If end of string, restore registers
- int 0x10 ; Print character in AL
- jmp print_enable_loop ; Loop to print the next character
- ; -------------------------
- ; Restore Registers and Continue
- ; -------------------------
- restore_registers_a20:
- pop si ; Restore source index
- pop di ; Restore destination index
- pop es ; Restore extra segment
- pop ds ; Restore data segment
- popf ; Restore flags
- sti ; Re-enable interrupts
- ; -------------------------
- ; GDT And TSS Loading Message
- ; -------------------------
- mov ax, 0x0000 ; Reset data segment for message output
- mov ds, ax
- mov ah, 0x0E ; Set up for character output
- mov bh, 0x00 ; Display page number
- mov si, msg_gdt_loading ; Load GDT loading message into SI
- gdt_print_loading:
- lodsb ; Load next byte from message
- cmp al, 0 ; Check for null terminator
- je tss_loading_msg ; If end of string, jump to GDT setup
- int 0x10 ; Print character in AL
- jmp gdt_print_loading ; Loop to print the next character
- tss_loading_msg:
- mov ax, 0x0000 ;
- mov ds, ax
- mov ah, 0x0E ;
- mov bh, 0x00 ;
- mov si, msg_tss_loading ;
- tss_print_loading:
- lodsb ;
- cmp al, 0 ;
- je gdt_setup ;
- int 0x10 ;
- jmp tss_print_loading ;
- ; -------------------------
- ; GDT and TSS Setup and Loading
- ; -------------------------
- gdt_setup:
- cli ; Disable interrupts during GDT setup
- lgdt [gdt_descriptor] ; Load GDT descriptor into GDTR
- push ds
- push es
- call init_tss ; Initialize the TSS
- pop es
- pop ds
- ; Display success message after loading GDT
- mov ax, 0x0000 ; Reset data segment for message output
- mov ds, ax
- mov ah, 0x0E ; Set up for character output
- mov bh, 0x00 ; Display page number
- mov si, msg_gdt_success ; Load GDT success message into SIs
- gdt_print_success:
- lodsb ; Load next byte from message
- cmp al, 0 ; Check for null terminator
- je tss_succsess_msg ; If end of string, proceed to protected mode
- int 0x10 ; Print character in AL
- jmp gdt_print_success ; Loop to print the next character
- tss_succsess_msg: ;
- mov ax, 0x0000 ;
- mov ds, ax
- mov ah, 0x0E ;
- mov bh, 0x00 ;
- mov si, msg_tss_success ;
- tss_print_success:
- lodsb ;
- cmp al, 0 ;
- je enter_protected_mode ;
- int 0x10 ;
- jmp tss_print_success ;
- ; -------------------------
- ; Enter Protected Mode
- ; -------------------------
- enter_protected_mode:
- cli ; Disable interrupts before entering protected mode
- mov eax, cr0
- or eax, 1 ; Set protected mode bit in CR0
- mov cr0, eax
- ; Far jump to update CS with GDT code segment (0x08)
- jmp 0x08:update_segments
- [BITS 32]
- update_segments:
- ; Set up segment registers for protected mode
- mov ax, 0x10 ; Load GDT data segment selector (0x10)
- mov ds, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
- mov ss, ax
- mov ax, 0x28 ; Load task register with our TSS descriptor
- ltr ax
- jmp kernel ; Jump to kernel code
- ; -------------------------
- ; Kernel Code (currently halting)
- ; -------------------------
- kernel:
- hlt ; Halt the CPU (placeholder for actual kernel code)
- ; -------------------------
- ; GDT Descriptor and TSS
- ; -------------------------
- section .data
- gdt_start:
- gdt:
- ; Null Descriptor
- dd 0x0
- dd 0x0
- ; Kernel Code Segment (DPL = 0)
- dw 0xFFFF ; Limit
- dw 0x0000 ; Base (lower 16 bits)
- db 0x00 ; Base (next 8 bits)
- db 10011010b ; Access byte
- db 11001111b ; Flags and limit (upper 4 bits)
- db 0x00 ; Base (upper 8 bits)
- ; Kernel Data Segment (DPL = 0)
- dw 0xFFFF ; Limit
- dw 0x0000 ; Base (lower 16 bits)
- db 0x00 ; Base (next 8 bits)
- db 10010010b ; Access byte
- db 11001111b ; Flags and limit (upper 4 bits)
- db 0x00 ; Base (upper 8 bits)
- ; User Code Segment (DPL = 3)
- dw 0xFFFF ; Limit
- dw 0x0000 ; Base (lower 16 bits)
- db 0x00 ; Base (next 8 bits)
- db 11111010b ; Access byte (DPL = 3)
- db 11001111b ; Flags and limit (upper 4 bits)
- db 0x00 ; Base (upper 8 bits)
- ; User Data Segment (DPL = 3)
- dw 0xFFFF ; Limit
- dw 0x0000 ; Base (lower 16 bits)
- db 0x00 ; Base (next 8 bits)
- db 11110010b ; Access byte (DPL = 3)
- db 11001111b ; Flags and limit (upper 4 bits)
- db 0x00 ; Base (upper 8 bits)
- ; TSS Descriptor
- .tss:
- dw 0x0067 ; Limit
- dd tss ; Base
- db 00000000b ; Flags and limit (upper 4 bits)
- db 10001001b ; Access byte
- gdt_end:
- ; GDT Descriptor (contains size and location of GDT)
- gdt_descriptor:
- dw gdt_end - gdt_start - 1 ; Size of the GDT (in bytes, minus 1)
- dd gdt_start
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement