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

📄 load.asm

📁 一个类linux的dos下开发的操作系统.
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; load.asm - load and run kernel inside M攂ius-format initial RAM disk
; Copyright (C) 2000 - Christopher Giese <geezer@execpc.com>
; http://www.execpc.com/~geezer/os/
;
; Tim Robinson's M攂ius OS: http://www.gaat.freeserve.co.uk/
;
; Assemble this file with NASM:
;	nasm -f bin -o load.com load.asm
; put your kernel into a Mobius initial RAM disk:
;	rdsk -o krnl.dsk krnl.x <other_files_here>
; then boot it:
;	load krnl.dsk
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	BITS 16
	ORG 100h		; .COM file

	mov ax,cs
	mov ds,ax
	mov ss,ax
	mov es,ax
	mov [real_mode_cs],ax
	mov sp,stack		; move the stack somewhere safe

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; before using 32-bit instructions, check for 32-bit CPU (386SX or better)
; I (Chris Giese) have not tested this code with 8088/'286 systems
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	pushf
		pushf
		pop bx		; old FLAGS -> BX
		mov ax,bx
		xor ah,70h	; try changing b14 (NT)...
		push ax		; ... or b13:b12 (IOPL)
		popf
		pushf
		pop ax		; new FLAGS -> AX
	popf
	xor ah,bh		; 32-bit CPU if we changed NT...
	mov si,cpu_msg
	and ah,70h		; ...or IOPL
	je near die

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; OK for pmode code to use DOS stack, but zero the top 16 bits of ESP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	xor eax,eax
	mov ax,sp
	mov esp,eax

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; we'll use this value a lot:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	xor ebp,ebp
	mov bp,cs
	shl ebp,4

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; patch things that depend on the load adr
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	mov eax,ebp
	mov [gdt3 + 2],ax	; CODE_SEL32
	mov [gdt4 + 2],ax	; DATA_SEL32
	mov [gdt5 + 2],ax	; CODE_SEL16
	mov [gdt6 + 2],ax	; DATA_SEL16
	shr eax,16
	mov [gdt3 + 4],al
	mov [gdt4 + 4],al
	mov [gdt5 + 4],al
	mov [gdt6 + 4],al
	mov [gdt3 + 7],ah
	mov [gdt4 + 7],ah
	; mov [gdt5 + 7],ah	; no, these are 16-bit
	; mov [gdt6 + 7],ah

	mov eax,tss
	add eax,ebp
	mov [gdt7 + 2],ax	; TSS_SEL
	shr eax,16
	mov [gdt7 + 4],al
	mov [gdt7 + 7],ah

	add [gdt_ptr + 2],ebp
	add [idt_ptr + 2],ebp

	add [vcpi_gdtr],ebp
	add [vcpi_idtr],ebp

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; get memory sizes from CMOS
; xxx - use BIOS calls
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	xor eax,eax
	mov al,18h
	out 70h,al
	in al,71h
	mov ah,al
	mov al,17h
	out 70h,al
	in al,71h
	shl eax,10		; Kbytes -> bytes
	mov [ext_mem],eax

	xor eax,eax
	mov al,16h
	out 70h,al
	in al,71h
	mov ah,al
	mov al,15h
	out 70h,al
	in al,71h
	shl eax,10		; Kbytes -> bytes
	mov [conv_mem],eax

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; grind the command line
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	mov si,80h
	lodsb
	xor ch,ch
	mov cl,al
	or cl,cl		; zero length means no command-line arg
	je usage_err
skip_spaces:
	lodsb
	cmp al,' '
	jne found_arg_start
	loop skip_spaces
usage_err:			; all spaces? how'd that happen?
	mov si,usage_msg
	jmp die

found_arg_start:
	lea dx,[si - 1]		; save ptr to arg in DX for use by OPEN
find_end:
	lodsb
	cmp al,' '
	je found_arg_end
	cmp al,0Dh
	loopne find_end
found_arg_end:
	xor al,al
	mov [si - 1],al		; convert 1st arg to ASCIZ (0-terminated)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; open the file named on the command line
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	mov ax,3D00h		; DOS "OPEN"; for read
	int 21h
	mov si,open_msg		; CY=1 if error
	jc near die
	mov bx,ax		; BX=file handle

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; validate file format
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	mov ah,3Fh		; DOS "READ"
	mov cx,32		; 32 bytes
	mov dx,end		; read to buffer that's just beyond this file
	int 21h
	jc read_error
	cmp ax,32
	je validate
read_error:
	mov si,read_msg
close_and_error:
	mov ah,3Eh		; DOS "CLOSE"
	int 21h
	jmp die

validate:			; Mobius-format initial RAM disk
	cmp dword [end],"RDSK"
	mov si,invalid_msg
	jne close_and_error
	cmp dword [end + 4],1	; number of files in RAM disk; must be >= 1
	jb close_and_error

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; get file size
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	mov ax,4202h		; DOS "LSEEK"; from end of file
	xor cx,cx
	xor dx,dx
	int 21h
	mov si,seek_msg
	jc close_and_error
	mov [file_len + 0],ax
	mov [file_len + 2],dx
	mov ax,4200h		; DOS "LSEEK"; from start of file
	xor cx,cx
	xor dx,dx
	int 21h
	jc close_and_error

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; see if enough conventional memory to load initial RAM disk
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	mov eax,ebp
	add eax,end		; linear adr of end of this .COM file
	add eax,[file_len]	; linear adr of end of loaded RAM disk
	cmp eax,[conv_mem]	; is it still within conventional mem?
	mov si,mem_msg
	jae close_and_error

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; load it
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	mov dx,end
%if 0
	mov cx,(32768 - end)	; ** sigh **
%else
	mov cx,end
	neg cx
	add cx,32768
%endif
	push ds
		jmp load2
load1:
		xor dx,dx
		mov ax,ds
		add ax,(32768 / 16)
		mov ds,ax
		mov cx,32768
load2:
		mov ah,3Fh	; DOS "READ"
		int 21h
		jnc load3
	pop ds
	jmp read_error
load3:
		or ax,ax
		jne load1	; ...until EOF
	pop ds

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; close input file
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	mov ah,3Eh		; DOS "CLOSE"
	int 21h

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; point to 1st file in initial RAM disk; see if it's DJGPP COFF
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	mov ebx,[end + 8]
	add ebx,end		; offset of end of this .COM file

COFF_MAGIC		EQU 0	; 0x014C
COFF_NUM_SECTS		EQU 2	; number of sections
COFF_OPTHDR_SIZE	EQU 16	; "optional" (aout) header size
COFF_FLAGS		EQU 18

AOUT_MAGIC		EQU 20 + 0 ; 0x010B
AOUT_ENTRY_POINT	EQU 20 + 16

COFF_TEXT_VIRT		EQU 20 + 28 + 40 * 0 + 12
COFF_TEXT_SIZE		EQU 20 + 28 + 40 * 0 + 16
COFF_TEXT_OFFSET	EQU 20 + 28 + 40 * 0 + 20

COFF_DATA_VIRT		EQU 20 + 28 + 40 * 1 + 12
COFF_DATA_SIZE		EQU 20 + 28 + 40 * 1 + 16
COFF_DATA_OFFSET	EQU 20 + 28 + 40 * 1 + 20

COFF_BSS_VIRT		EQU 20 + 28 + 40 * 2 + 12
COFF_BSS_SIZE		EQU 20 + 28 + 40 * 2 + 16
COFF_BSS_OFFSET		EQU 20 + 28 + 40 * 2 + 20

	cmp word [bx + COFF_MAGIC],014Ch
	jne not_coff
	cmp word [bx + COFF_NUM_SECTS],3
	jne not_coff
	cmp word [bx + COFF_OPTHDR_SIZE],28
	jne not_coff
	test word [bx + COFF_FLAGS],2
	je not_coff
	cmp word [bx + AOUT_MAGIC],010Bh
	je coff_ok

; xxx - make sure all sections in same 4 meg address space
; xxx - make sure .text section doesn't overlap others

not_coff:
	mov si,coff_msg
	jmp die
coff_ok:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; get sizes of .text, .data, and .bss sections; sum is kernel size
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	mov edx,[bx + COFF_TEXT_SIZE]
	add edx,[bx + COFF_DATA_SIZE]
	add edx,[bx + COFF_BSS_SIZE]

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; see if enough extended memory to copy kernel to 1 meg
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	mov edi,100000h
	cmp edx,[ext_mem]
	jb mem_ok

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; see if enough conventional memory to copy kernel beyond loaded file
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	mov edi,ebp
	add edi,end		; linear adr of end of this .COM file
	add edi,[file_len]	; linear adr of end of initial RAM disk
	add edi,4095
	and di,0F000h		; round up to page (4K) boundary
	mov eax,edi
	add eax,edx
	cmp eax,[conv_mem]
	mov si,mem_msg
	jae near close_and_error
mem_ok:
	mov [load_adr],edi

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; enable A20 line using 'AT' ('Linux') method, then test if it worked
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	cli

	call kbd
	mov al,0D1h
	out 64h,al
	call kbd
	mov al,0DFh
	out 60h,al
	call kbd

	call test_a20
	jne a20_ok

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; oop, try the 'Vectra' method
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	call kbd
	mov al,0DFh
	out 64h,al
	call kbd

	mov si,a20_msg
	call test_a20
	je near die
a20_ok:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; no more errors are possible, and we're done with DOS,
; so move to unreal mode. But first, check for virtual 8086 mode:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	smsw ax
	test al,1		; look at PE bit of MSW (CR0)
	je near real

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; in V86 mode; check for VCPI (e.g. DOS with EMM386 loaded)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	mov ax,0DE00h
	int 67h
	cmp ah,0
	mov si,v86_msg
	jne near die

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; use VCPI to switch from V86 mode to paged pmode
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	mov edi,ebp		; find 4K-aligned mem for page table
	add edi,(page_info + 4095)
	and di,0F000h		; EDI=linear adr of page table

	mov eax,edi
	add eax,4096		; linear adr of page dir, 4K above table
	mov [vcpi_cr3],eax

	mov eax,edi
	sub edi,ebp		; DI=offset of page table
	add di,4096		; point to page dir
	or al,7			; ring 3, writable, present
	mov [di + 0],eax	; page dir[0] -> linear adr of page table
	sub di,4096		; back to page table; VCPI will fill it

	mov si,gdt8		; get 3 VCPI descriptors to here
	mov ax,0DE01h
	int 67h
	cmp ah,0
	mov si,vcpi_err_msg
	jne near die
	push dword 0		; disable interrupts (set IF=0)...
	popfd			; ...set IOPL=0, and clear the NT bit
	mov esi,ebp
	add esi,vcpi_control_block
	mov ax,0DE0Ch		; switch from V86 mode to paged pmode
	int 67h			; jump to vcpi_to_pmode32

	BITS 32

vcpi_to_pmode32:		; now in ring 0 paged pmode
	mov eax,cr0
	and eax,7FFFFFFFh	; turn off paging
	mov cr0,eax
	xor eax,eax
	mov cr3,eax		; flush TLB
	jmp CODE_SEL16:pmode32_to_pmode16

	BITS 16

pmode32_to_pmode16:		; finish switching to 16-bit pmode

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -