|
|
-
- %define GDT_Paragraph 0x1000
- %define GDT (GDT_Paragraph*16)
- %define GDT_CodeSegIndex 1
- %define GDT_DataSegIndex 2
- %define GDT_CodeSeg16Index 3
- %define GDT_DataSeg16Index 4
- %define GDT_Selector(DescriptorIndex, TableIndicator, RequestorPrivLevel) ((DescriptorIndex << 3) | ((TableIndicator & 1) << 2) | (RequestorPrivLevel & 0x3))
- %define GDT_CodeSegSelector GDT_Selector(GDT_CodeSegIndex, 0, 0)
- %define GDT_DataSegSelector GDT_Selector(GDT_DataSegIndex, 0, 0)
- %define GDT_CodeSeg16Selector GDT_Selector(GDT_CodeSeg16Index, 0, 0)
- %define GDT_DataSeg16Selector GDT_Selector(GDT_DataSeg16Index, 0, 0)
-
- %define VIDEO 0xB8000
- %define VIDEO_X_RES 80
- %define VIDEO_Y_RES 25
- %define ScreenCoord(x, y) (2*(VIDEO_X_RES*(y)+(x)))
-
- ; GDT Stuff
- %define Data 0000b
- %define DataMutable 0010b
- %define DataShrink 0100b
- %define DataShrinkMutable 0110b
- %define Code 1000b
- %define CodeRead 1010b
- %define CodeOwnRing 1100b
- %define CodeOwnRingRead 1110b
-
- %macro GDT_NULL_ENTRY 1 ; address
- %assign address %1
- lea di, [address]
- xor ax, ax
- mov cx, 4
- rep stosw
-
- %assign GDT_COUNT (GDT_COUNT+1)
- %endmacro
-
- %macro GDT_ENTRY 6 ; address base limit type privilege bits32
- %assign address %1
-
- %assign base %2
- %assign limit %3
-
- %assign type (%4 & 0xf)
- %assign reserved (1<<4)
- %assign privilege ((%5 & 0x3) << 5)
- %assign present (1<<7)
- %assign access (present | privilege | reserved | type)
-
- %assign bits32 ((%6 & 1) << 2)
- %assign granularity (1<<3)
- %assign flags (granularity | bits32)
-
- %assign limit_0_15 (limit & 0xffff)
- %assign limit_16_19 ((limit >> 16) & 0xf)
- %assign base_0_15 (base & 0xffff)
- %assign base_16_23 ((base >> 16) & 0xff)
- %assign base_24_31 ((base >> 24) & 0xff)
-
- mov WORD [es:(address + 0)], limit_0_15
- mov WORD [es:(address + 2)], base_0_15
- mov WORD [es:(address + 4)], base_16_23 | (access << 8)
- mov WORD [es:(address + 6)], limit_16_19 | (flags << 4) | (base_24_31 << 8)
-
- %assign GDT_COUNT (GDT_COUNT+1)
- %endmacro
-
- %define IOKeyData 0x60
- %define InKeyStatus 0x64
- %define OutKeyCommand 0x64
-
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- Enable_A20:
- ; Enables A20 gate using:the BIOS, keyboard controller, or Fast A20
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- pushad ;Preserve registers
- pushfd ;Preserve EFLAGS because we might disable interrupts
- mov ax,0x2402 ;INT 15h AX=2402h: Query A20 status
- int 0x15 ;Check to see if A20 gate is enabled
- jc A20_No_BIOS ;Error? Don't use BIOS to enable gate
- test al,1 ;Test Bit 0 of AL
- je A20_Enabled ;A20 gate already enabled
- mov ax,0x2401 ;INT 15h AX=2401h: Enable A20 gate
- int 0x15 ;Use BIOS to enable A20 gate
- jc A20_No_BIOS ;Error? Don't use BIOS to enable gate
- or ah,ah ;Test AH
- jnz A20_No_BIOS ;Non-zero? A20 gate may not be enabled
- A20_Enabled:
- popfd ;Restore EFLAGS
- popad ;Restore registers
- ret ;Return
- A20_No_BIOS:
- mov ax,0x2403 ;INT 15h AX=2403h: Query A20 support
- int 0x15 ;Call BIOS to find out how the A20 gate can be enabled
- jc A20_KBD ;Error? Assume that keyboard controller is the only option
- test bx,1 ;Bit 0:Keyboard controller supported
- je A20_KBD ;BIOS indicates that keyboard controller is supported
- test bx,2 ;Bit 1:Fast A20 supported
- je FAST_A20 ;BIOS indicated that Fast A20 is supported
- call Check_A20 ;Test A20 gate manually
- jc A20_Enabled ;A20 gate already enabled
- A20_Fail:
- call A20_OUT_Wait ;"Unable to enable A20 gate!"
- cli ;Disable interrupts
- hlt ;Halt machine
- FAST_A20:
- in al,0x92 ;Read System Control Port A
- test al,2 ;Test Fast A20 bit
- jnz A20_Fail ;Bit already set, failed to enable A20 gate
- or al,2 ;Set Bit 1:Enable Fast A20
- and al,0xFE ;Always clear Bit 0 so that machine does not reboot
- out 0x92,al ;Write to port 92h
- call Check_A20 ;Check A20 gate
- jc A20_Enabled ;Success?
- cli ;No? something must have gone wrong
- hlt ;Clear interrupts and halt machine
- A20_KBD:
- cli ;Disable interrupts
- mov cx,50 ;Number of attempts to enable gate
- Use_KBD:
- call A20_OUT_Wait ;Wait for keyboard
- mov al,0xAD ;Disable Keyboard
- out 0x64,al ;Wait for Keyboard
- mov al,0xD0 ;Read Controller Output Port
- out 0x64,al
- call A20_IN_Wait ;Wait for Keyboard
- in al,0x60 ;Read Data Port
- push ax ;Save
- call A20_OUT_Wait ;Wait for Keyboard
- mov al,0xD1 ;Write Controller Output Port
- out 0x64,al
- call A20_OUT_Wait ;Wait for Keyboard
- pop ax ;Get port data back
- or al,10b ;Bit 1: Enable A20 gate
- out 0x60,al ;Write to data port
- call A20_OUT_Wait ;Wait for Keyboard
- mov al,0xAE ;Enable Keyboard
- out 0x64,al
- call A20_OUT_Wait ;Wait for Keyboard
- call Check_A20 ;Verify that gate is enabled
- jc A20_Enabled ;Yes? Return
- loop Use_KBD ;No? Keep trying
- jmp A20_Fail ;Could not enable gate after 50 tries
- A20_OUT_Wait:
- in al,0x64 ;Read status register
- test al,10b ;Is port ready?
- jnz A20_OUT_Wait ;Nope, wait
- ret ;Yep, continue
- A20_IN_Wait:
- in al,0x64 ;Read status register
- test al,1b ;Is port ready?
- jz A20_IN_Wait ;Nope, wait
- ret ;Yep, continue
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- Check_A20:
- ; Test if A20 gate is enabled by comaparing the value in FFFF:7E0E
- ; with the VBR boot signature at 0000:7DFE
- ; Out: Carry flag set if A20 gate is enabled
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- pushad ;Preserve registers
- push es
- mov ax, 0xFFFF
- mov es, ax ;Extra segment:FFFF
- cmp WORD [es:0x7DFE + 16], 0xAAFF ;See if boot signature is wrapped at FFFF:7E0E (Meaning FFFF:7E0E = 0:7DFE)
- stc ; Assume we didn't wrap, yes A20
- jne .End
- clc ; We did wrap, no A20
- .End:
- pop es
- popad
- ret
-
-
-
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- Go32Bit:
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- call Enable_A20
-
- ; Set screen mode
- mov ax, 0x0003 ; AH=0 (Change video mode), AL=13h (Mode) = 320x200 - 256 colors
- mov bx, 0x0000
- int 0x10 ; Video BIOS interrupt
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; Global Descriptor Table ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;
- mov ax, GDT_Paragraph
- mov es, ax
- mov cx, 4096
- lea si, [GO32_COPY_BEGIN]
- xor di, di
- rep movsb
-
- %assign GDT_COUNT 0
-
- GDT_NULL_ENTRY 0
- GDT_ENTRY (GDT_CodeSegIndex*8), 0x00000000, 0xffffffff, CodeRead, 0, 1
- GDT_ENTRY (GDT_DataSegIndex*8), 0x00000000, 0xffffffff, DataMutable, 0, 1
- GDT_ENTRY (GDT_CodeSeg16Index*8), 0x00000000, 0xffffffff, CodeRead, 0, 0
- GDT_ENTRY (GDT_DataSeg16Index*8), 0x00000000, 0xffffffff, DataMutable, 0, 0
- cli
- lgdt [GDT_Record]
-
- mov eax, cr0
- or al, 1 ; set PE (Protection Enable) bit in CR0 (Control Register 0)
- mov cr0, eax
-
- jmp ClearPrefetchQueue
- nop
- nop
- ClearPrefetchQueue:
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Manually assembled long jump ;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- db 0x66 ; 32bit override
- db 0xea ; Long jump
- dd ProtectedModeBaby ; Absolute address
- dw GDT_CodeSegSelector ; Descriptor Selector
-
- GDT_Record:
- dw (GDT_COUNT*8) - 1 ; Size of GDT in bytes minus 1
- dd 0x1000*16 ; Linear address of GDT
-
-
-
-
- align 512
- BITS 32
- GO32_COPY_BEGIN:
-
- segment Go32Bit vstart=GDT
- GDT_SPACE: times (GDT_COUNT*8) db 0
-
- ProtectedModeBaby:
-
- ; Update Other Segments
- mov ax, GDT_DataSegSelector
- mov ds, ax
- mov ss, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
-
-
- ; Setup stack
- mov esp, (100 << 20) - 1 ; 100M Addressable
- mov ebp, esp
-
- ; Space for dynamic variables
- sub esp, 200*4 ; 200 32-bit integers
-
-
- push ebp
-
- DrawStuff:
- xor ecx, ecx
- xor edx, edx
- lea edi, [VIDEO]
-
- mov ebp, dword [Zoom]
- sar ebp, 9
- jnz .DrawLoop
-
- mov ebp, 0x7fffffff
-
- .DrawLoop:
- mov eax, [Px]
- shr eax, 4
- add eax, ecx
- imul eax, eax
-
- mov ebx, eax
-
- mov eax, [Py]
- shr eax, 4
- add eax, edx
- add eax, edx
- imul eax, eax
-
- add ebx, eax
-
- mov eax, [ColorOffset]
- push edx
- xor edx, edx
- idiv ebp
- pop edx
-
- xchg eax, ebx
-
- add ax, bx
-
- mov al, ah
-
- stosw
-
- inc ecx
- cmp ecx, VIDEO_X_RES
- jne .DrawLoop
-
- xor ecx, ecx
- inc edx
- cmp edx, VIDEO_Y_RES-2
- jne .DrawLoop
-
- pop ebp
-
-
- cld
-
- xor eax, eax
-
- in al, IOKeyData ; Get the scan code from the keyboard
-
- test al, 0x80
- jnz .ThereWasNothing
-
- cmp al, 75; left
- je .KeyLeft
-
- cmp al, 72; up
- je .KeyUp
-
- cmp al, 80; right
- je .KeyDown
-
- cmp al, 77; down
- je .KeyRight
-
- cmp al, 51; <
- je .KeyLess
-
- cmp al, 52; >
- je .KeyGreater
-
- cmp al, 1 ; Escape
- je .KeyEscape
-
-
-
- .ThereWasNothing:
- mov [Key], byte ' '
- jmp .PrintKeyLegend
- ; lea esi, [ProtectedWelcomeStr]
-
- .KeyEscape:
- call Reboot
- jmp .PrintKeyLegend
-
- .KeyLeft:
- mov [Key], byte 'L'
- add [Px], dword -1
- jmp .PrintKeyLegend
- .KeyUp:
- mov [Key], byte 'U'
- add [Py], dword -1
- jmp .PrintKeyLegend
- .KeyRight:
- mov [Key], byte 'R'
- add [Px], dword 1
- jmp .PrintKeyLegend
- .KeyDown:
- mov [Key], byte 'D'
- add [Py], dword 1
- jmp .PrintKeyLegend
- .KeyLess:
- mov [Key], byte '<'
- add [Zoom], dword -1
- jmp .PrintKeyLegend
- .KeyGreater:
- mov [Key], byte '>'
- add [Zoom], dword 1
-
-
-
- .PrintKeyLegend:
- lea esi, [ThereWasSomethingStr]
-
- lea edi, [VIDEO + ScreenCoord((80-11), 24)]
- mov ah, 0x2f
- .print_loop:
- mov al, BYTE [esi]
- test al, al
- jz .break_print_loop
- stosw
- inc esi
- jmp .print_loop
- .break_print_loop:
-
- lea esi, [VarLabels]
- lea edi, [ConversionBuffer]
- mov ecx, VarLabelsLength
- call CopyData
-
- lea esi, [ConversionBuffer]
- lea edi, [VIDEO + ScreenCoord(0, 24)]
- mov ah, 0x0f
- call PrintString
-
-
- ; lea esi, [ConversionBuffer]
- mov eax, dword [Px]
- sar eax, 4
- call IntToString
-
- ; lea esi, [ConversionBuffer]
- ; ecx set by IntToString
- mov edx, 7
- mov al, ' '
- call RightJustifyString
-
- ; esi still ConversionBuffer
- mov ecx, edx
- lea edi, [VIDEO + ScreenCoord(StrXStart, 24)]
- mov ah, 0x70
- call PrintString
-
-
- ; lea esi, [ConversionBuffer]
- mov eax, dword [Py]
- sar eax, 4
- call IntToString
-
- ; lea esi, [ConversionBuffer]
- ; ecx set by IntToString
- mov edx, 7
- mov al, ' '
- call RightJustifyString
-
- ; esi still ConversionBuffer
- mov ecx, edx
- lea edi, [VIDEO + ScreenCoord(StrYStart, 24)]
- mov ah, 0x70
- call PrintString
-
-
-
- add [ColorOffset], dword 1
-
- jmp DrawStuff
-
-
-
-
-
- %include "Strings32.nasm"
-
- Halt:
- cli
- hlt
- jmp Halt
-
- ; ------------------------------------------------------------------------------
-
- Reboot:
- in al, 0x64
- test al, 0x2 ; Wait for an empty Input Buffer
- jne Reboot
- mov al, 0xFE
- out 0x64, al ; Send the reboot call to the keyboard controller
- jmp Reboot
-
- ;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Strings
- ;;;;;;;;;;;;;;;;;;;;;;;;
- VarLabels: db "X:"
- StrXStart equ $-VarLabels
- db " "
- db "Y:"
- StrYStart equ $-VarLabels
- db " "
- VarLabelsLength equ $-VarLabels
- ProtectedWelcomeStr: db " Placeholder for SingOS - 32 bit edition! ", 0
- ProtectedWelcomeStrLength equ $-ProtectedWelcomeStr
- TestStr: db "hello, world"
- TestStrLength equ $-TestStr
- ThereWasSomethingStr: db " KEY = '"
- Key: db " ' ", 0
- Px: dd 0
- Py: dd 0
- ColorOffset: dd 0
- Zoom: dd (4<<9)
- ConversionBuffer: times 40 db 0
- align 512
|