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

📄 start.asm

📁 一个类linux的dos下开发的操作系统.
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; stripped-down startup code
; - no #pragma startup/#pragma exit/atexit()...
; - no freeing of unused memory for TINY memory model (using INT 21h AH=4Ah)
; - no exit code		- no heap
; - TINY memory model only	- no NULL pointer checking
; - no interrupt handling	- no DOS version checking
;
; Thanks, John Fine, for helping with the invalid entry point problem.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

SEGMENT _TEXT PUBLIC CLASS=CODE
	resb 100h
GLOBAL __code
__code:

..start:
	mov ax,cs
	mov ds,ax
	cmp ax,0040h			; bootstrap or .COM file?
	jbe boot		; xxx - is there a better test for DOS?
	inc byte [__dos]
boot:
	mov es,ax
	mov ss,ax
	mov sp,stack

	xor ax,ax			; the stack is in the BSS,
	mov di,__bss			; so don't push/pop until
	mov cx,__end			; the BSS is zeroed
	sub cx,di
	rep stosb

; check for 32-bit CPU and get memory sizes
	call cpu_is_32bit
	call get_convmem_size
	call get_extmem_size

; xxx - set conv_mem (far pointer) and ext_mem (linear adr)
; xxx - adjust extmem_size and ext_mem if XMS present
; xxx - adjust conv_mem_size and conv_mem based on __end

EXTERN _main
	call _main			; call C code

exit:
	mov ax,0E07h			; *** BEEEP ***
	int 10h
	mov ah,0			; await key pressed
	int 16h

	mov al,[__dos]
	or al,al
	jne dos_exit
	int 19h				; re-start the boot process
dos_exit:
	mov ax,4C01h
	int 21h

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; name:			_intr
; action:		replaces buggy Turbo C 2.0 intr() function
; in:			interrupt number and pointer to REGPACK on stack
; out:			(nothing)
; modifies:		REGPACK
; minimum CPU:		8088
; notes:		C proto: void intr(int intnum, struct REGPACK *preg);
;			Turbo C 2.0 intr() does not appear to load BP
;			register correctly
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

GLOBAL _intr
_intr:
	push bp
		mov bp,sp

; save old registers
		pushf
		push es
		push ds
		push di
		push si
		push bp
		push dx
		push cx
		push bx
		push ax

; set interrupt vector, using self-modifying code
			mov bx,word [bp + 4]
			mov byte [cs:INT_NUM],bl

; load new registers
			mov bx,word [bp + 6]
			push bx
			push ds

			mov ax,word [bx + 0]	; [preg + 0]
			push word [bx + 2]	; [preg + 2]; BX
			mov cx,word [bx + 4]	; [preg + 4]
			mov dx,word [bx + 6]	; [preg + 6]
			mov bp,word [bx + 8]	; [preg + 8]
			mov si,word [bx + 10]	; [preg + 10]
			mov di,word [bx + 12]	; [preg + 12]
			push word [bx + 14]	; [preg + 14]; DS
			mov es,word [bx + 16]	; [preg + 16]
			push word [bx + 18]	; [preg + 18]; FLAGS

			popf
			pop ds
			pop bx

; perform interrupt (CDh = opcode for INT instruction)
			db 0CDh
INT_NUM:
			db 10h

; save new registers
			push bx
			push ds
			pushf

			mov bx,sp
			mov ds,[ss:bx + 6]
			mov bx,[ss:bx + 8]

			pop word [bx + 18]	; [preg + 18]; FLAGS
			mov word [bx + 16],es	; [preg + 16]
			pop word [bx + 14]	; [preg + 14]; DS
			mov word [bx + 12],di	; [preg + 12]
			mov word [bx + 10],si	; [preg + 10]
			mov word [bx + 8],bp	; [preg + 8]
			mov word [bx + 6],dx	; [preg + 6]
			mov word [bx + 4],cx	; [preg + 4]
			pop word [bx + 2]	; [preg + 2]; BX
			mov word [bx + 0],ax	; [preg + 0]

			add sp,4

; restore old registers
		pop ax
		pop bx
		pop cx
		pop dx
		pop bp
		pop si
		pop di
		pop ds
		pop es
		popf
	pop bp
	ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; name:			cpu_is_32bit
; action:		checks for 32-bit CPU
; in:			(nothing)
; out:			__got_32bit_cpu set
; modifies:		(nothing)
; minimum CPU:		8088
; notes:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

cpu_is_32bit:
	push bx
	push ax
		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 al,al		; zero AL
		xor ah,bh		; 32-bit CPU if we changed NT...
		and ah,70h		; ...or IOPL
		mov [__got_32bit_cpu],ah
	pop ax
	pop bx
	ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; name:			get_convmem_size
; action:		gets conventional memory size using BIOS calls
; in:			(nothing)
; out:			__conv_mem_size set
; modifies:		(nothing)
; minimum CPU:		8088
; notes:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

get_convmem_size:
	push dx
	push ax
		int 12h

		xor dx,dx	; move to DX multiplies by 256
		mov dl,ah
		mov ah,al
		xor al,al

		shl ax,1	; multiply by 4 (x1024 total)
		rcl dx,1
		shl ax,1
		rcl dx,1
		mov [__conv_mem_size + 0],ax
		mov [__conv_mem_size + 2],dx
	pop ax
	pop dx
	ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; name:			get_extmem_size
; action:		gets extended memory size using BIOS calls
; in:			(nothing)
; out:			(nothing)
; modifies:		maybe the high 16 bits of some registers
; minimum CPU:		8088 (386+ for INT 15h AX=E820h)
; notes:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

get_extmem_size:
	push bp
	    mov bp,sp
	    push es
	    push di
	    push si
	    push dx
	    push cx
	    push bx
	    push ax

; got a 32-bit CPU or not?
		mov al,[__got_32bit_cpu]
		or al,al
		je mem3			; can't use INT 15h AX=E820h

; try INT 15h AX=E820h
		push ds
		pop es
		mov di,buffer_e820
		xor esi,esi
		mov edx,534D4150h	; "SMAP"
		xor ebx,ebx
mem1:
		mov ecx,20h
		mov eax,0000E820h
		int 15h
		jc mem3
		cmp dword [es:di + 16],1 ; type 1 memory (available to OS)
		jne mem2
		cmp dword [es:di],100000h ; check only extended memory
		jb mem2
		add esi,[es:di + 8]
mem2:
		or ebx,ebx
		jne mem1

		mov eax,esi
		mov edx,esi
		shr edx,16
		jmp short mem7		; DX:AX=RAM top
mem3:
; try INT 15h AX=E801h
		mov ax,0E801h
		int 15h
		jc mem4
		mov dx,bx		; BX=ext mem >=16M, in 64K
					; move to DX multiples by 64K
		xor bx,bx
		mov bl,ah		; AX=ext mem 1M-16M, in K
		mov ah,al		; multiply by 256
		xor al,al

		shl ax,1		; multiply by 4 (x1024 total)
		rcl bx,1
		shl ax,1
		rcl bx,1

		add dx,bx
		jmp short mem7		; DX:AX=RAM top
mem4:
; try INT 15h AH=88h
		mov ax,8855h
		int 15h			; CY=error is not reliable...
		cmp ax,8855h		; ...so make sure AL is modified
		jne mem5
		mov ax,88AAh
		int 15h			; AX=ext mem size, in K
		cmp ax,88AAh
		je mem6
mem5:
		xor dx,dx		; move to DX multiplies by 256
		mov dl,ah
		mov ah,al
		xor al,al

		shl ax,1		; multiply by 4 (x1024 total)
		rcl dx,1
		shl ax,1
		rcl dx,1

		jmp short mem7		; DX:AX=RAM top
mem6:
		xor ax,ax
		xor dx,dx
mem7:
		mov [__ext_mem_size + 0],ax
		mov [__ext_mem_size + 2],dx
	    pop ax
	    pop bx
	    pop cx
	    pop dx
	    pop si
	    pop di
	    pop es
	pop bp
	ret

; xxx - restore VCPI code
; xxx - make sure XMS memory alloc works when EMM386 loaded

; alternate code to enter pmode; should work with Bochs
; xxx - uncomment this, use it if INT 15h AH=89h fails
%if 0

unhand	EQU	0

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; name:			kbd
; action:		waits until 8042 keyboard controller ready
;			to accept a command or data byte
; modifies:		AL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

kbd0:
	jmp short $+2	; a delay (probably not effective nor necessary)
	in al,60h	; read and discard data/status from 8042
kbd:
	jmp short $+2	; delay
	in al,64h
	test al,1	; output buffer (data _from_ keyboard) full?
	jnz kbd0	; yes, read and discard
	test al,2	; input buffer (data _to_ keyboard) empty?
	jnz kbd		; no, loop
	ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; name:			set_a20_at
; action:		enables/disables A20 at 8042 output port,
;			using D0h (read output port) and D1h
;			(write output port) command bytes to
;			toggle bit b1 of the output port
; in:			AH=0 to disable A20, AH != 0 to enable A20
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

set_a20_at:
	push si
	push ax
	pushf

; Yay, feedback! Chase told me it works better if I shut off interrupts:
		cli
		call kbd
		mov al,0D0h	; 8042 command byte to read output port
		out 64h,al

await:
		in al,64h
		test al,1	; output buffer (data _from_ keyboard) full?
		jz await	; no, loop

		in al,60h	; read output port
		or ah,ah

⌨️ 快捷键说明

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