⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 start.asm

📁 一个类linux的dos下开发的操作系统.
💻 ASM
📖 第 1 页 / 共 2 页
字号:
		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 + -