1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
; Data for the Loader.
%define LoaderAddress 0000h
%define LoaderSegment 9000h
; Return the data at the address given by the offset "x".
%define LA(x) LoaderAddress + x
; Start
[BITS 16]
[ORG 0000h]
jmp Start
StartMsg db 'Starting up...',0dh,0ah,00h
NewLine db 0dh,0ah,00h
PrintString:
pusha
PrintStringLoop:
lodsb
or al,al
je PrintStringEnd
mov ah,0eh
mov bx,0007h
int 10h
jmp PrintStringLoop
PrintStringEnd:
popa
ret
PrintChar:
push ax
PrintCharMSB:
shr al,4
cmp al,0Ah
jge PrintCharMSBAlpha
PrintCharMSBNum:
add al,30h
jmp PrintCharMSBEnd
PrintCharMSBAlpha:
add al,37h
PrintCharMSBEnd:
mov ah,0Eh
mov bx,0007h
int 10h
PrintCharLSB:
pop ax
and al,0fh
cmp al,0Ah
jge PrintCharLSBAlpha
PrintCharLSBNum:
add al,30h
jmp PrintCharLSBEnd
PrintCharLSBAlpha:
add al,37h
PrintCharLSBEnd:
mov ah,0Eh
mov bx,0007h
int 10h
ret
PrintWord:
push ax
mov al,ah
call PrintChar
pop ax
call PrintChar
ret
PrintDWord:
push eax
mov si,LA(NewLine)
call PrintString
push eax
shr eax,16
call PrintWord
pop eax
call PrintWord
pop eax
ret
; enables the a20 gate
; the usual keyboard-enable-a20-gate-stuff
enable_a20:
call _a20_loop
jnz _enable_a20_done
mov al,0xd1
out 0x64,al
call _a20_loop
jnz _enable_a20_done
mov al,0xdf
out 0x60,al
_a20_loop:
mov ecx,0x20000
_loop2:
jmp short _c
_c:
in al,0x64
test al,0x2
loopne _loop2
_enable_a20_done:
ret
Start:
; Initialize the segment register for datas.
mov ax,LoaderSegment
mov ds,ax
mov es,ax
mov ss,ax
xor ax,ax
mov sp,ax
; Display the welcome note
mov si,LA(StartMsg)
call PrintString
cli
mov ax,LoaderSegment
mov ds,ax
call enable_a20 ; enable a20 gate
lgdt [ss:gdt]
smsw ax
or al,1
lmsw ax
db 0eah ; opcode for far jump (to set CS correctly)
dw clear_pipe,08h
[BITS 32]
clear_pipe:
; mov ax,10h
; mov ds,ax
; mov ss,ax
; mov esp, 080000h
; mov byte [ds:0B8000h], 'P'
; mov byte [ds:0B8001h], 1Bh
; Infinit loop
InfLoop:
jmp InfLoop
gdt:
; the first entry serves 2 purposes: as the GDT header and as the first descriptor
; note that the first descriptor (descriptor 0) is always a NULL-descriptor
db 0xFF ; full size of GDT used
db 0xff ; which means 8192 descriptors * 8 bytes = 2^16 bytes
dw gdt ; address of GDT (dword)
dd 0
; descriptor 1 - code:
dd 0x0000ffff ; base - limit: 0 - 0xfffff * 4K
dd 0x008f9a00 ; type: 16 bit, exec-only conforming, <present>, privilege 0
; descriptor 2 - data/stack:
dd 0x0000ffff ; base - limit: 0 - 0xfffff * 4K
dd 0x008f9200 ; type: 16 bit, data read/write, <present>, privilege 0 |
Partager