📄 boot2.asm
字号:
.386p ;we have a 386
code_seg segment use16
assume cs:code_seg
jmp start
DESC struc ;descriptor structure
L15_L0 dw 0 ;limit 15...0
B15_B0 dw 0 ;base 15...0
B23_B16 db 0 ;base 23...16
ACCESS db 0 ;P,DPL,DT,DATA|CODE,EXPAND-DOWN|CONFIRMING,W|R,A
LIM_FLAGS db 0 ;G,DEF|BIG,RES,AV,limit 19...16
B31_B24 db 0 ;base 31...24
DESC ends
DESC0 DESC <0,0,0,0,0,0> ;dummy descriptor
DESC1 DESC <0ffffh,0000h,00h,9ah,0cfh,00h> ;flat code
DESC2 DESC <0ffffh,0000h,00h,92h,0cfh,00h> ;flat data
DESC3 DESC <0ffffh,2000h,00h,9ah,0cfh,00h> ;kernel code
DESC4 DESC <007ffh,1000h,00h,92h,040h,00h> ;IDT memory
DESC5 DESC <0ffffh,0C000h,09h,9ah,0cfh,00h> ;load.com code
GDT_LIMIT dw $-DESC0-1
KERNEL_SECTORS equ 16
KERNEL_BASE equ 9C00h
sect_to_read dw 18
head db ?
track db ?
a20failed db 'A-20 enabling failed!',13,10,0
rebootmsg db 13,10,'Press any key to reboot',13,10,0
gdt_lim dw ?
gdt_bse dd 00001800h
display proc near
prnt:
lodsb
or al,al
jz over
mov ah,0eh
mov bx,0007
int 10h
jmp prnt
over:
ret
display endp
key macro
mov ah,0
int 16h
endm
wait_for_buf_empty proc near
wait_empty:
in al,64h ;test 1st bit of status port
test al,2 ;input reg has data for 8042
jnz wait_empty
ret
wait_for_buf_empty endp
wait_for_data proc near
wait_data: ;test 0th bit of status port
in al,64h
test al,1
jz wait_data
ret
wait_for_data endp
enable_a20 proc near
call wait_for_buf_empty
mov al,0d0h ;read output port--the output reg should be
out 64h,al ;empty. we get data in 0x60
call wait_for_data
xor ax,ax
in al,60h
push ax ;save output port
call wait_for_buf_empty
mov al,0d1h ;write to output port
out 64h,al ;next byte written to 0x60 goes to o/p port
call wait_for_buf_empty
pop ax
or al,00000010b ;set 1st bit -- A-20 gate
out 60h,al
call wait_for_buf_empty
mov al,0d0h ;read o/p port
out 64h,al
call wait_for_data
in al,60h ;test for 1st bit (A-20 enabled?)
test al,2
jz failure
mov al,1 ;al=1 success
jmp a20over
failure:
mov al,0 ;al=0 failure
a20over:
ret
enable_a20 endp
make32 macro seg,off
mov eax,0
mov ebx,0
mov ax,seg
mov bx,off
shl eax,4
add eax,ebx
endm
init_pic proc near
;0th bit-icw4 required,4th bit clr-Edge triggering
;with edge-trigger,IRQ is indicated by transition
;of signal from low to high(standard).
mov al,00010001b
out 20h,al ;icw1 master
out 0a0h,al ;icw1 slave
mov dx,21h
mov al,018h ;master PIC -> 0x18 - 0x1F (24 - 31)
out dx,al ;icw2 parent
mov al,020h ;slave PIC -> 0x20 - 0x27 (32 - 39)
out 0a1h,al ;icw2 slave
mov al,0100b
out dx,al ;icw3 master,IRQ2 is connected to slave
mov al,2
out 0a1h,al ;icw3 slave,master IRQ to which slave is connected
mov al,1 ;0th bit-8086 mode
out dx,al ;icw4 master
out 0a1h,al ;icw4 slave
mov al,011111011b
out dx,al ;ocw1 master,mask IRQ0-IRQ7 except IRQ2
or al,0100b
out 0a1h,al ;ocw1 slave,MASK IRQ8-IRQ15
ret
init_pic endp
diskmotoroff proc near
mov dx,03f2h ;Digital Output Register
in al,dx
and al,0fh ;clear motor-on bits
out dx,al ;output to DOR
ret
diskmotoroff endp
dispnum macro a
mov al,a
mov ah,0eh
mov bx,0007
int 10h
endm
disph proc near
mov cl,4
mov ch,8
disph1:
rol eax,cl
push eax
and al,0fh
add al,30h
cmp al,'9'
jbe disph2
add al,7
disph2:
dispnum al
pop eax
dec ch
jnz disph1
ret
disph endp
set_gdt proc near
mov si,offset DESC0
mov ax,180h
mov es,ax
mov di,0
mov ax,GDT_LIMIT
inc ax
mov cx,ax
cld ;increment si & di
rep movsb ;move string from ds:si to es:di,times-cx
mov ax,GDT_LIMIT
mov gdt_lim,ax
ret
set_gdt endp
start:
push cs
pop ds ;initialize ds
cli ;setup stack
mov ax,3000h
mov ss,ax
mov sp,0ffffh
sti
;load the kernel
mov ax,KERNEL_BASE
mov es,ax
mov ax,KERNEL_SECTORS
.if ax <= 18
mov bx,0 ;loads into ES:BX
mov ah,02 ;command
mov dl,0 ;drive
mov al,KERNEL_SECTORS ;number of sectors to read
mov ch,0 ;track
mov cl,1 ;starting sector
mov dh,1 ;head
int 13h ;BIOS disk interrupt
.else
mov si,KERNEL_SECTORS ;number of sectors to read
mov head,1 ;head
mov track,0 ;track
.while si > 0
mov ah,02 ;command
mov dl,0 ;drive
mov al,byte ptr sect_to_read;number of sectors to read
mov ch,track ;track
mov cl,1 ;starting sector
mov dh,head ;head
int 13h ;BIOS disk interrupt
add bx,512*18 ;increase offset
.if head == 0
mov head,1
.else
mov head,0
inc track
.endif
sub si,18 ;subtract num sectors read
jns cont
mov si,0
cont:
.if si > 18
mov sect_to_read,18
.else
mov sect_to_read,si
.endif
.endw
.endif
call diskmotoroff ;BIOS does not turn off motor in pmode
in al,070h ;Mask NMI, this is necessary before moving to protected mode
or al,080h
out 070h,al
cli
call enable_a20 ;enable A-20
.if al == 0
mov si,offset a20failed
call display
mov si,offset rebootmsg
call display
key
jmp last
.endif
call init_pic ;initialize PIC
; make32 ds,offset DESC0
; mov GDT_BASE,eax
call set_gdt
lgdt fword ptr gdt_lim ;load GDTR
mov eax,cr0
or al,1
mov cr0,eax ;set pmode bit of cr0
jmp hang ;not required, but i dont like to change this
hang:
mov ax,10h
mov ds,ax
mov fs,ax
mov gs,ax
mov es,ax
mov ss,ax
mov esp,9ffffh
sti
db 0eah ;machine code for jmp 0x0028:0x0000
dw 0000h
dw 0028h
last:
db 0eah ;if something goes wrong, reboot
dw 0000h
dw 0ffffh
org 8704
code_seg ends
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -