📄 start.asm
字号:
jne sa1
and al,0FDh ; AND ~2 to disable
jmp sa2
sa1:
or al,2 ; OR 2 to enable
sa2:
mov ah,al
call kbd
mov al,0D1h ; 8042 command byte to write output port
out 64h,al
call kbd
mov al,ah ; the value to write
out 60h,al
call kbd
popf
pop ax
pop si
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; name: set_a20_vectra
; action: enables/disables A20 at 8042 output port,
; using DFh command byte/DDh command byte
; in: AH=0 to disable A20, AH != 0 to enable A20
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
set_a20_vectra:
push si
push ax
pushf
cli
call kbd
or ah,ah
jne sav1
mov al,0DDh ; disable
jmp short sav2
sav1:
mov al,0DFh ; enable
sav2:
out 64h,al
call kbd
popf
pop ax
pop si
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; name: verify_a20
; out (A20 enabled): ZF=0
; out (A20 NOT enabled):ZF=1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
verify_a20:
push ax
push ds
push es
xor ax,ax
mov ds,ax
dec ax
mov es,ax
mov ax,[es:10h] ; read word at FFFF:0010 (1 meg)
not ax ; 1's complement
push word [0] ; save word at 0000:0000 (0)
mov [0],ax ; word at 0 = ~(word at 1 meg)
mov ax,[0] ; read it back
cmp ax,[es:10h] ; fail if word at 0 == word at 1 meg
pop word [0]
pop es
pop ds
pop ax
ret ; if ZF=1, the A20 gate is NOT enabled
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; name: _run_pmode_kernel
; action: (what it says)
; in: physical entry point on stack
; out: -1 if A20 gate could not be enabled
; modifies: AX and the high 16 bits of some registers
; minimum CPU: '386
; notes: C prototype:
; unsigned run_pmode_kernel(unsigned long phys_entry_pt);
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GLOBAL _run_pmode_kernel
_run_pmode_kernel:
push bp
mov bp,sp
push bx
; try 'AT' method of enabling A20
mov ah,1
call set_a20_at
call verify_a20
jne a20_ok
; that didn't work; try the 'Vectra' method
call set_a20_vectra
call verify_a20
jne a20_ok
mov ax,-1
pop bx
pop bp
ret
a20_ok:
; (self-modifying code)
mov eax,[bp + 4]
mov [entry + 2],eax
xor ebx,ebx
mov bx,ds
shl ebx,4
add [gdt1 + 2],ebx
; convert SS:SP to ESP
xor ebx,ebx
mov bx,sp
add ebx,eax
mov esp,ebx
; disable interrupts (set IF=0), set IOPL=0, and clear the NT bit
push dword 0
popfd
; enter pmode
lgdt [gdt1]
mov ebx,cr0
inc bx
mov cr0,ebx
; load data segment registers
mov ax,LDATA32
mov ds,ax
mov ss,ax
mov es,ax
mov fs,ax
mov gs,ax
mov byte [es:dword 0B8004h],'O'
mov byte [es:dword 0B8006h],'K'
entry:
; word [entry+0]: JMP 66 EA
; dword [entry+2]: offset 00 00 00 00
; word [entry+6]: selector 08 00
jmp LCODE32:dword 0
%else
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; name: _run_pmode_kernel
; action: (what it says)
; in: physical entry point on stack
; out: error value from INT 15h AH=89h
; modifies: AX and the high 16 bits of some registers
; minimum CPU: '386
; notes: C prototype:
; unsigned run_pmode_kernel(unsigned long phys_entry_pt);
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GLOBAL _run_pmode_kernel
_run_pmode_kernel:
push bp
mov bp,sp
push es
push si
push bx
; (self-modifying code)
mov eax,[bp + 4]
mov [entry + 1],eax
xor ebx,ebx
mov bx,ds
shl ebx,4
add [gdt1 + 2],ebx
add [gdt2 + 2],ebx
mov eax,ebx
shr eax,16
add [gdt3 + 2],bx
adc [gdt3 + 4],al
adc [gdt3 + 7],ah
add [gdt5 + 2],bx
adc [gdt5 + 4],al
adc [gdt5 + 7],ah
; pmode code descriptor must have same base as real mode CS << 4
add [gdt6 + 2],bx
adc [gdt6 + 4],al
adc [gdt6 + 7],ah
; convert SS:SP to ESP
xor ebx,ebx
mov bx,sp
add ebx,eax
mov esp,ebx
mov si,ds
mov es,si
mov si,gdt
mov bx,2820h
mov ah,89h
; disable interrupts (set IF=0), set IOPL=0, and clear the NT bit
push dword 0
popfd
int 15h
jnc pmode
mov al,ah
pop bx
pop si
pop es
pop bp
ret
[BITS 32]
pmode:
mov byte [es:0B8004h],'O'
mov byte [es:0B8006h],'K'
mov ax,es
mov ds,eax
mov ss,eax
mov fs,eax
mov gs,eax
entry:
; byte [entry+0]: JMP EA
; dword [entry+2]: offset 00 00 00 00
; word [entry+6]: selector 08 00
jmp LCODE32:dword 0
unhand:
mov ax,LDATA32
mov es,ax
mov byte [es:0B8000h],'!'
jmp $
[BITS 16]
%endif
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; name: __REALCVT
; action: traps attempt to use printf() with floating point
; in: (nothing)
; out: DOES NOT RETURN
; modifies: AX
; minimum CPU: 8088
; notes:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GLOBAL __REALCVT
__REALCVT:
jmp exit
SEGMENT _DATA PUBLIC CLASS=DATA ALIGN=2
GLOBAL __data
__data:
GLOBAL __dos
__dos:
db 0
GLOBAL __got_32bit_cpu
__got_32bit_cpu:
db 0
GLOBAL __conv_mem_size
__conv_mem_size:
dd 0
GLOBAL __ext_mem_size
__ext_mem_size:
dd 0
buffer_e820:
times 42 db 0
gdt:
dd 0, 0 ; NULL descriptor
gdt1:
dw gdt_end - gdt - 1 ; GDT pseudo-descriptor
;; dd gdt ; linear, physical adr of GDT
dw gdt, 0 ; TLINK chokes; must use 16-bit address here
dw 0
gdt2:
dw idt_end - idt - 1 ; IDT pseudo-descriptor
;; dd idt ; linear, physical adr of IDT
dw idt, 0 ; TLINK chokes; must use 16-bit address here
dw 0
DATA32 equ $-gdt
gdt3:
dw 0FFFFh ; DS
dw 0
db 0
db 92h ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular, 32-bit
db 0
LDATA32 equ $-gdt
gdt4:
dw 0FFFFh ; ES
dw 0
db 0
db 92h ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular, 32-bit
db 0
gdt5:
dw 0FFFFh ; SS
dw 0
db 0
db 92h ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular, 32-bit
db 0
CODE32 equ $-gdt
gdt6:
dw 0FFFFh ; CS
dw 0
db 0
db 9Ah ; present, ring 0, code, non-conforming, readable
db 0CFh ; page-granular, 32-bit
db 0
gdt7:
dd 0, 0 ; (used by INT 15h AH=89h for BIOS CS)
LCODE32 equ $-gdt
gdt8:
dw 0FFFFh ; CS
dw 0
db 0
db 9Ah ; present, ring 0, code, non-conforming, readable
db 0CFh ; page-granular, 32-bit
db 0
gdt_end:
idt:
%rep 48
dw unhand ; low 16 bits of ISR offset
dw CODE32 ; selector
db 0
db 8Eh ; present, ring 0, 32-bit intr gate
dw 0 ; high 16 bits of ISR (unhand >> 16)
%endrep
idt_end:
; I want to align the BSS to a 512-byte boundary to avoid error 9
; from INT 13h (DMA crossed 64K boundary), but either NASM or the
; .OBJ format won't let me.
SEGMENT _BSS PUBLIC CLASS=BSS ALIGN=2
GLOBAL __bss
__bss:
times 4096 dw 0 ; 8K stack
stack:
; align "_end" to a paragraph (16-byte) boundary
SEGMENT _BSSEND PUBLIC CLASS=BSSEND ALIGN=16
; align "_end" to a page (4096-byte) boundary
; xxx - this triggers a bug in NASM
; SEGMENT _BSSEND PUBLIC CLASS=BSSEND ALIGN=4096
GLOBAL __end
__end:
GROUP DGROUP _TEXT _DATA _BSS _BSSEND
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -