|
|
@ -12,6 +12,9 @@ |
|
|
|
%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 |
|
|
@ -25,10 +28,10 @@ |
|
|
|
|
|
|
|
%macro GDT_NULL_ENTRY 1 ; address |
|
|
|
%assign address %1 |
|
|
|
lea di, [address] |
|
|
|
xor ax, ax |
|
|
|
mov cx, 4 |
|
|
|
rep stosw |
|
|
|
lea di, [address] |
|
|
|
xor ax, ax |
|
|
|
mov cx, 4 |
|
|
|
rep stosw |
|
|
|
|
|
|
|
%assign GDT_COUNT (GDT_COUNT+1) |
|
|
|
%endmacro |
|
|
@ -55,10 +58,10 @@ |
|
|
|
%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) |
|
|
|
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 |
|
|
@ -75,81 +78,81 @@ Enable_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 |
|
|
|
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 |
|
|
|
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!" |
|
|
|
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? |
|
|
|
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 |
|
|
|
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 |
|
|
|
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 |
|
|
|
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 |
|
|
|
in al,0x64 ;Read status register |
|
|
|
test al,1b ;Is port ready? |
|
|
|
jz A20_IN_Wait ;Nope, wait |
|
|
|
ret ;Yep, continue |
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
|
@ -160,15 +163,15 @@ Check_A20: |
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
|
|
|
|
|
|
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) |
|
|
|
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 |
|
|
|
jne .End |
|
|
|
clc ; We did wrap, no A20 |
|
|
|
.End: |
|
|
|
pop es |
|
|
|
pop es |
|
|
|
popad |
|
|
|
ret |
|
|
|
|
|
|
@ -179,38 +182,38 @@ Check_A20: |
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
|
|
Go32Bit: |
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
|
|
call Enable_A20 |
|
|
|
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 |
|
|
|
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 |
|
|
|
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 |
|
|
|
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] |
|
|
|
lgdt [GDT_Record] |
|
|
|
|
|
|
|
mov eax, cr0 |
|
|
|
or al, 1 ; set PE (Protection Enable) bit in CR0 (Control Register 0) |
|
|
|
mov cr0, eax |
|
|
|
mov eax, cr0 |
|
|
|
or al, 1 ; set PE (Protection Enable) bit in CR0 (Control Register 0) |
|
|
|
mov cr0, eax |
|
|
|
|
|
|
|
jmp ClearPrefetchQueue |
|
|
|
jmp ClearPrefetchQueue |
|
|
|
nop |
|
|
|
nop |
|
|
|
ClearPrefetchQueue: |
|
|
@ -218,14 +221,14 @@ ClearPrefetchQueue: |
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
|
|
;; Manually assembled long jump ;; |
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
|
|
db 0x66 ; 32bit override |
|
|
|
db 0xea ; Long jump |
|
|
|
dd ProtectedModeBaby ; Absolute address |
|
|
|
dw GDT_CodeSegSelector ; Descriptor Selector |
|
|
|
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 |
|
|
|
dw (GDT_COUNT*8) - 1 ; Size of GDT in bytes minus 1 |
|
|
|
dd 0x1000*16 ; Linear address of GDT |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -240,269 +243,231 @@ 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 |
|
|
|
mov ax, GDT_DataSegSelector |
|
|
|
mov ds, ax |
|
|
|
mov ss, ax |
|
|
|
mov es, ax |
|
|
|
mov fs, ax |
|
|
|
mov gs, ax |
|
|
|
|
|
|
|
; Setup stack |
|
|
|
mov esp, 0x8000000 |
|
|
|
mov ebp, esp |
|
|
|
mov esp, 0x8000000 |
|
|
|
mov ebp, esp |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DrawStuff: |
|
|
|
xor ecx, ecx |
|
|
|
xor edx, edx |
|
|
|
lea edi, [VIDEO] |
|
|
|
xor ecx, ecx |
|
|
|
xor edx, edx |
|
|
|
lea edi, [VIDEO] |
|
|
|
|
|
|
|
mov ebp, dword [Zoom] |
|
|
|
sar ebp, 9 |
|
|
|
jnz .DrawLoop |
|
|
|
mov ebp, dword [Zoom] |
|
|
|
sar ebp, 9 |
|
|
|
jnz .DrawLoop |
|
|
|
|
|
|
|
mov ebp, 0x7fffffff |
|
|
|
mov ebp, 0x7fffffff |
|
|
|
|
|
|
|
.DrawLoop: |
|
|
|
mov eax, [Px] |
|
|
|
shr eax, 4 |
|
|
|
add eax, ecx |
|
|
|
imul eax, eax |
|
|
|
mov eax, [Px] |
|
|
|
shr eax, 4 |
|
|
|
add eax, ecx |
|
|
|
imul eax, eax |
|
|
|
|
|
|
|
mov ebx, eax |
|
|
|
mov ebx, eax |
|
|
|
|
|
|
|
mov eax, [Py] |
|
|
|
shr eax, 4 |
|
|
|
add eax, edx |
|
|
|
add eax, edx |
|
|
|
imul eax, eax |
|
|
|
mov eax, [Py] |
|
|
|
shr eax, 4 |
|
|
|
add eax, edx |
|
|
|
add eax, edx |
|
|
|
imul eax, eax |
|
|
|
|
|
|
|
add ebx, eax |
|
|
|
add ebx, eax |
|
|
|
|
|
|
|
mov eax, [ColorOffset] |
|
|
|
push edx |
|
|
|
xor edx, edx |
|
|
|
idiv ebp |
|
|
|
pop edx |
|
|
|
mov eax, [ColorOffset] |
|
|
|
push edx |
|
|
|
xor edx, edx |
|
|
|
idiv ebp |
|
|
|
pop edx |
|
|
|
|
|
|
|
xchg eax, ebx |
|
|
|
xchg eax, ebx |
|
|
|
|
|
|
|
add ax, bx |
|
|
|
add ax, bx |
|
|
|
|
|
|
|
mov al, ah |
|
|
|
mov al, ah |
|
|
|
|
|
|
|
stosw |
|
|
|
|
|
|
|
inc ecx |
|
|
|
cmp ecx, 80 |
|
|
|
jne .DrawLoop |
|
|
|
inc ecx |
|
|
|
cmp ecx, VIDEO_X_RES |
|
|
|
jne .DrawLoop |
|
|
|
|
|
|
|
xor ecx, ecx |
|
|
|
inc edx |
|
|
|
cmp edx, 25-1 |
|
|
|
jne .DrawLoop |
|
|
|
xor ecx, ecx |
|
|
|
inc edx |
|
|
|
cmp edx, VIDEO_Y_RES-2 |
|
|
|
jne .DrawLoop |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cld |
|
|
|
|
|
|
|
xor eax, eax |
|
|
|
xor eax, eax |
|
|
|
|
|
|
|
in al, IOKeyData ; Get the scan code from the keyboard |
|
|
|
in al, IOKeyData ; Get the scan code from the keyboard |
|
|
|
|
|
|
|
test al, 0x80 |
|
|
|
jnz .ThereWasNothing |
|
|
|
test al, 0x80 |
|
|
|
jnz .ThereWasNothing |
|
|
|
|
|
|
|
cmp al, 75; left |
|
|
|
je .KeyLeft |
|
|
|
cmp al, 75; left |
|
|
|
je .KeyLeft |
|
|
|
|
|
|
|
cmp al, 72; up |
|
|
|
je .KeyUp |
|
|
|
cmp al, 72; up |
|
|
|
je .KeyUp |
|
|
|
|
|
|
|
cmp al, 80; right |
|
|
|
je .KeyDown |
|
|
|
cmp al, 80; right |
|
|
|
je .KeyDown |
|
|
|
|
|
|
|
cmp al, 77; down |
|
|
|
je .KeyRight |
|
|
|
cmp al, 77; down |
|
|
|
je .KeyRight |
|
|
|
|
|
|
|
cmp al, 51; < |
|
|
|
je .KeyLess |
|
|
|
cmp al, 51; < |
|
|
|
je .KeyLess |
|
|
|
|
|
|
|
cmp al, 52; > |
|
|
|
je .KeyGreater |
|
|
|
cmp al, 52; > |
|
|
|
je .KeyGreater |
|
|
|
|
|
|
|
cmp al, 1 ; Escape |
|
|
|
je .KeyEscape |
|
|
|
cmp al, 1 ; Escape |
|
|
|
je .KeyEscape |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.ThereWasNothing: |
|
|
|
mov [Key], byte ' ' |
|
|
|
jmp .PrintKeyLegend |
|
|
|
; lea esi, [ProtectedWelcomeStr] |
|
|
|
mov [Key], byte ' ' |
|
|
|
jmp .PrintKeyLegend |
|
|
|
; lea esi, [ProtectedWelcomeStr] |
|
|
|
|
|
|
|
.KeyEscape: |
|
|
|
call Reboot |
|
|
|
jmp .PrintKeyLegend |
|
|
|
call Reboot |
|
|
|
jmp .PrintKeyLegend |
|
|
|
|
|
|
|
.KeyLeft: |
|
|
|
mov [Key], byte 'L' |
|
|
|
add [Px], dword -1 |
|
|
|
jmp .PrintKeyLegend |
|
|
|
mov [Key], byte 'L' |
|
|
|
add [Px], dword -1 |
|
|
|
jmp .PrintKeyLegend |
|
|
|
.KeyUp: |
|
|
|
mov [Key], byte 'U' |
|
|
|
add [Py], dword -1 |
|
|
|
jmp .PrintKeyLegend |
|
|
|
mov [Key], byte 'U' |
|
|
|
add [Py], dword -1 |
|
|
|
jmp .PrintKeyLegend |
|
|
|
.KeyRight: |
|
|
|
mov [Key], byte 'R' |
|
|
|
add [Px], dword 1 |
|
|
|
jmp .PrintKeyLegend |
|
|
|
mov [Key], byte 'R' |
|
|
|
add [Px], dword 1 |
|
|
|
jmp .PrintKeyLegend |
|
|
|
.KeyDown: |
|
|
|
mov [Key], byte 'D' |
|
|
|
add [Py], dword 1 |
|
|
|
jmp .PrintKeyLegend |
|
|
|
mov [Key], byte 'D' |
|
|
|
add [Py], dword 1 |
|
|
|
jmp .PrintKeyLegend |
|
|
|
.KeyLess: |
|
|
|
mov [Key], byte '<' |
|
|
|
add [Zoom], dword -1 |
|
|
|
jmp .PrintKeyLegend |
|
|
|
mov [Key], byte '<' |
|
|
|
add [Zoom], dword -1 |
|
|
|
jmp .PrintKeyLegend |
|
|
|
.KeyGreater: |
|
|
|
mov [Key], byte '>' |
|
|
|
add [Zoom], dword 1 |
|
|
|
mov [Key], byte '>' |
|
|
|
add [Zoom], dword 1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.PrintKeyLegend: |
|
|
|
lea esi, [ThereWasSomethingStr] |
|
|
|
lea esi, [ThereWasSomethingStr] |
|
|
|
|
|
|
|
lea edi, [VIDEO+(80*24 + (80-11))*2] |
|
|
|
; lea edi, [VIDEO+(80*2)*12+30*2] |
|
|
|
mov ah, 0x0f |
|
|
|
lea edi, [VIDEO + ScreenCoord((80-11), 24)] |
|
|
|
mov ah, 0x2f |
|
|
|
.print_loop: |
|
|
|
mov al, BYTE [esi] |
|
|
|
test al, al |
|
|
|
jz .break_print_loop |
|
|
|
mov al, BYTE [esi] |
|
|
|
test al, al |
|
|
|
jz .break_print_loop |
|
|
|
stosw |
|
|
|
inc esi |
|
|
|
jmp .print_loop |
|
|
|
inc esi |
|
|
|
jmp .print_loop |
|
|
|
.break_print_loop: |
|
|
|
|
|
|
|
lea edi, [VIDEO + (80*24 + 1)*2] |
|
|
|
push edi |
|
|
|
mov ecx, 34 |
|
|
|
xor eax, eax |
|
|
|
rep stosd |
|
|
|
pop edi |
|
|
|
|
|
|
|
mov eax, dword [Px] |
|
|
|
sar eax, 4 |
|
|
|
call IntToString |
|
|
|
|
|
|
|
add edi, 12*2 |
|
|
|
lea edi, [VIDEO + ScreenCoord(1, 24)] |
|
|
|
mov ecx, 34 |
|
|
|
mov eax, 0 |
|
|
|
rep stosd |
|
|
|
|
|
|
|
lea esi, [ConversionBuffer] |
|
|
|
mov eax, dword [Px] |
|
|
|
sar eax, 4 |
|
|
|
call IntToString |
|
|
|
|
|
|
|
mov eax, dword [Py] |
|
|
|
sar eax, 4 |
|
|
|
call IntToString |
|
|
|
push ecx |
|
|
|
|
|
|
|
add edi, 12*2 |
|
|
|
mov eax, [Zoom] |
|
|
|
sar eax, 9 |
|
|
|
call IntToString |
|
|
|
lea esi, [ConversionBuffer] |
|
|
|
mov edx, 6 |
|
|
|
call RightJustifyString |
|
|
|
|
|
|
|
add [ColorOffset], dword 1 |
|
|
|
|
|
|
|
jmp DrawStuff |
|
|
|
HALT: |
|
|
|
cli |
|
|
|
hlt |
|
|
|
jmp HALT |
|
|
|
lea edi, [VIDEO + ScreenCoord(1, 24)] |
|
|
|
mov ah, 0x0f |
|
|
|
call PrintString |
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
|
|
IntToString: |
|
|
|
; Puts the stringified version of eax on the stack |
|
|
|
; IN: eax = number to write |
|
|
|
; IN: edi = base of where to write string |
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
|
|
pushad |
|
|
|
lea esi, [ConversionBuffer] |
|
|
|
pop eax |
|
|
|
call IntToString |
|
|
|
|
|
|
|
lea esi, [ConversionBuffer] |
|
|
|
lea edi, [VIDEO + ScreenCoord(40, 24)] |
|
|
|
mov ah, 0x0f |
|
|
|
call PrintString |
|
|
|
|
|
|
|
mov ebx, 10 ; Divisor |
|
|
|
|
|
|
|
xor ecx, ecx ; Digit count starts at 0 |
|
|
|
|
|
|
|
mov [.sign], byte ' ' |
|
|
|
; add edi, 12*2 |
|
|
|
|
|
|
|
test eax, eax |
|
|
|
jns .loop_divide |
|
|
|
|
|
|
|
neg eax |
|
|
|
mov [.sign], byte '-' |
|
|
|
|
|
|
|
.loop_divide: ; finds digits and pushes them to stack |
|
|
|
test eax, eax |
|
|
|
jz .break_loop_divide |
|
|
|
xor edx, edx |
|
|
|
idiv ebx ; edx = (edx:eax)%ebx, eax = (edx:eax)/ebx |
|
|
|
inc ecx ; Increase digit count |
|
|
|
mov byte [.buffer + ecx], dl |
|
|
|
jmp .loop_divide |
|
|
|
.break_loop_divide: |
|
|
|
|
|
|
|
add edi, 20 |
|
|
|
; mov eax, dword [Py] |
|
|
|
; sar eax, 4 |
|
|
|
; call IntToString |
|
|
|
|
|
|
|
test ecx, ecx |
|
|
|
jnz .NotZero |
|
|
|
; add edi, 12*2 |
|
|
|
; mov eax, [Zoom] |
|
|
|
; sar eax, 9 |
|
|
|
; call IntToString |
|
|
|
|
|
|
|
mov ax, (0x0f << 8) | '0' |
|
|
|
stosw |
|
|
|
popad |
|
|
|
ret |
|
|
|
add [ColorOffset], dword 1 |
|
|
|
|
|
|
|
.NotZero: |
|
|
|
jmp DrawStuff |
|
|
|
|
|
|
|
sub edi, ecx |
|
|
|
sub edi, ecx |
|
|
|
|
|
|
|
mov ah, 0x0f |
|
|
|
mov al, byte [.sign] |
|
|
|
stosw |
|
|
|
|
|
|
|
.loop_print: |
|
|
|
test ecx, ecx |
|
|
|
jz .break_loop_print |
|
|
|
mov al, byte [.buffer + ecx] |
|
|
|
add al, '0' ; Convert to ascii |
|
|
|
mov ah, 0x0f |
|
|
|
stosw |
|
|
|
dec ecx |
|
|
|
jmp .loop_print |
|
|
|
|
|
|
|
.break_loop_print: |
|
|
|
|
|
|
|
popad |
|
|
|
ret |
|
|
|
.buffer times 40 db 0 |
|
|
|
.sign db ' ' |
|
|
|
|
|
|
|
%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 |
|
|
|
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 |
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;; |
|
|
|
ProtectedWelcomeStr: db " Placeholder for SingOS - 32 bit edition! ", 0 |
|
|
|
ThereWasSomethingStr: db " KEY = '" |
|
|
|
Key: db " ' ", 0 |
|
|
|
Px: dd 0 |
|
|
|
Py: dd 0 |
|
|
|
ColorOffset: dd 0 |
|
|
|
Zoom: dd (4<<9) |
|
|
|
align 512 |
|
|
|
ProtectedWelcomeStr: db " Placeholder for SingOS - 32 bit edition! ", 0 |
|
|
|
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 |