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

📄 klib88.s

📁 MINIX2.0操作系统源码 MINIX2.0操作系统源码
💻 S
📖 第 1 页 / 共 3 页
字号:
! Load and return the word at the far pointer  segment:offset.

_mem_rdw:
	mov	cx,ds		! save ds
	pop	dx		! return adr
	pop	ds		! segment
	pop	bx		! offset
	sub	sp,#2+2		! adjust for parameters popped
	mov	ax,(bx)		! load the word to return
	mov	ds,cx		! restore ds
	jmp	(dx)		! return


!*===========================================================================*
!*				reset					     *
!*===========================================================================*
! PUBLIC void reset();
! Reset the system.
! In real mode we simply jump to the reset address.

_reset:
	jmpf	0,0xFFFF


!*===========================================================================*
!*				mem_vid_copy				     *
!*===========================================================================*
! PUBLIC void mem_vid_copy(u16 *src, unsigned dst, unsigned count);
!
! Copy count characters from kernel memory to video memory.  Src, dst and
! count are character (word) based video offsets and counts.  If src is null
! then screen memory is blanked by filling it with blank_color.

MVC_ARGS	=	2 + 2 + 2 + 2	! 2 + 2 + 2
!			es  di  si  ip	 src dst ct

_mem_vid_copy:
	push	si
	push	di
	push	es
	mov	bx, sp
	mov	si, MVC_ARGS(bx)	! source
	mov	di, MVC_ARGS+2(bx)	! destination
	mov	dx, MVC_ARGS+2+2(bx)	! count
	mov	es, _vid_seg		! destination is video segment
	cld				! make sure direction is up
mvc_loop:
	and	di, _vid_mask		! wrap address
	mov	cx, dx			! one chunk to copy
	mov	ax, _vid_size
	sub	ax, di
	cmp	cx, ax
	jbe	0f
	mov	cx, ax			! cx = min(cx, vid_size - di)
0:	sub	dx, cx			! count -= cx
	shl	di, #1			! byte address
	test	si, si			! source == 0 means blank the screen
	jz	mvc_blank
mvc_copy:
	rep				! copy words to video memory
	movs
	jmp	mvc_test
mvc_blank:
	mov	ax, _blank_color	! ax = blanking character
	rep
	stos				! copy blanks to video memory
	!jmp	mvc_test
mvc_test:
	shr	di, #1			! word addresses
	test	dx, dx
	jnz	mvc_loop
mvc_done:
	pop	es
	pop	di
	pop	si
	ret


!*===========================================================================*
!*				vid_vid_copy				     *
!*===========================================================================*
! PUBLIC void vid_vid_copy(unsigned src, unsigned dst, unsigned count);
!
! Copy count characters from video memory to video memory.  Handle overlap.
! Used for scrolling, line or character insertion and deletion.  Src, dst
! and count are character (word) based video offsets and counts.

VVC_ARGS	=	2 + 2 + 2 + 2	! 2 + 2 + 2
!			es  di  si  ip 	 src dst ct

_vid_vid_copy:
	push	si
	push	di
	push	es
	mov	bx, sp
	mov	si, VVC_ARGS(bx)	! source
	mov	di, VVC_ARGS+2(bx)	! destination
	mov	dx, VVC_ARGS+2+2(bx)	! count
	mov	es, _vid_seg		! use video segment
	cmp	si, di			! copy up or down?
	jb	vvc_down
vvc_up:
	cld				! direction is up
vvc_uploop:
	and	si, _vid_mask		! wrap addresses
	and	di, _vid_mask
	mov	cx, dx			! one chunk to copy
	mov	ax, _vid_size
	sub	ax, si
	cmp	cx, ax
	jbe	0f
	mov	cx, ax			! cx = min(cx, vid_size - si)
0:	mov	ax, _vid_size
	sub	ax, di
	cmp	cx, ax
	jbe	0f
	mov	cx, ax			! cx = min(cx, vid_size - di)
0:	sub	dx, cx			! count -= cx
	shl	si, #1
	shl	di, #1			! byte addresses
	rep
   eseg movs				! copy video words
	shr	si, #1
	shr	di, #1			! word addresses
	test	dx, dx
	jnz	vvc_uploop		! again?
	jmp	vvc_done
vvc_down:
	std				! direction is down
	add	si, dx			! start copying at the top
	dec	si
	add	di, dx
	dec	di
vvc_downloop:
	and	si, _vid_mask		! wrap addresses
	and	di, _vid_mask
	mov	cx, dx			! one chunk to copy
	lea	ax, 1(si)
	cmp	cx, ax
	jbe	0f
	mov	cx, ax			! cx = min(cx, si + 1)
0:	lea	ax, 1(di)
	cmp	cx, ax
	jbe	0f
	mov	cx, ax			! cx = min(cx, di + 1)
0:	sub	dx, cx			! count -= cx
	shl	si, #1
	shl	di, #1			! byte addresses
	rep
   eseg	movs				! copy video words
	shr	si, #1
	shr	di, #1			! word addresses
	test	dx, dx
	jnz	vvc_downloop		! again?
	cld				! C compiler expect up
	!jmp	vvc_done
vvc_done:
	pop	es
	pop	di
	pop	si
	ret


!*===========================================================================*
!*			      level0					     *
!*===========================================================================*
! PUBLIC void level0(void (*func)(void))
! Not very interesting in real mode, see p_level0.
!
_level0:
	mov	bx, sp
	jmp	@2(bx)


!*===========================================================================*
!*				klib_init_prot				     *
!*===========================================================================*
! PUBLIC void klib_init_prot();
! Initialize klib for protected mode by patching some real mode functions
! at their starts to jump to their protected mode equivalents, according to
! the patch table.  Saves a lot of tests on the "protected_mode" variable.
! Note that this function must be run in real mode, for it writes the code
! segment.  (One otherwise has to set up a descriptor, etc, etc.)

klib_init_prot:
	mov	si,#patch_table
kip_next:
	lods			! original function
	mov	bx,ax
  cseg	movb	(bx),#JMP_OPCODE ! overwrite start of function by a long jump
	lods			! new function - target of jump
	sub	ax,bx		! relative jump
	sub	ax,#3		! adjust by length of jump instruction
  cseg	mov	1(bx),ax	! set address
	cmp	si,#end_patch_table ! end of table?
	jb	kip_next
kip_done:
	ret


!*===========================================================================*
!*			variants for protected mode			     *
!*===========================================================================*
! Some routines are different in protected mode.
! The only essential difference is the handling of segment registers.
! One complication is that the method of building segment descriptors is not
! reentrant, so the protected mode versions must not be called by interrupt
! handlers.


!*===========================================================================*
!*				p_cp_mess				     *
!*===========================================================================*
! The real mode version attempts to be efficient by passing raw segments but
! that just gets in the way here.

p_cp_mess:
	cld
	pop	dx
	pop	bx		! proc
	pop	cx		! source clicks
	pop	ax		! source offset
#if CLICK_SHIFT != HCLICK_SHIFT + 4
#error /* the only click size supported is 256, to avoid slow shifts here */
#endif
	addb	ah,cl		! calculate source offset
	adcb	ch,#0		! and put in base of source descriptor
	mov	_gdt+DS_286_OFFSET+DESC_BASE,ax
	movb	_gdt+DS_286_OFFSET+DESC_BASE_MIDDLE,ch
	pop	cx		! destination clicks
	pop	ax		! destination offset
	addb	ah,cl		! calculate destination offset
	adcb	ch,#0		! and put in base of destination descriptor
	mov	_gdt+ES_286_OFFSET+DESC_BASE,ax
	movb	_gdt+ES_286_OFFSET+DESC_BASE_MIDDLE,ch
	sub	sp,#2+2+2+2+2

	push	ds
	push	es
	mov	ax,#DS_286_SELECTOR
	mov	ds,ax
	mov	ax,#ES_286_SELECTOR
	mov	es,ax

  eseg	mov	0,bx		! proc no. of sender from arg, not msg
	mov	ax,si
	mov	bx,di
	mov	si,#2		! src offset is now 2 relative to start of seg
	mov	di,si		! and destination offset
	mov	cx,#Msize-1	! word count
	rep
	movs
	mov	di,bx
	mov	si,ax
	pop	es
	pop	ds
	jmp	(dx)


!*===========================================================================*
!*				p_portio_setup				     *
!*===========================================================================*
! The port_read, port_write, etc. functions need a setup routine that uses
! a segment descriptor.
p_portio_setup:
	mov	ax,4+2(bp)	! source/destination address in dx:ax
	mov	dx,4+2+2(bp)
	mov	_gdt+DS_286_OFFSET+DESC_BASE,ax
	movb	_gdt+DS_286_OFFSET+DESC_BASE_MIDDLE,dl
	xor	bx,bx		! bx = 0 = start of segment
	mov	ax,#DS_286_SELECTOR ! ax = segment selector
	mov	cx,4+2+4(bp)	! count in bytes
	mov	dx,4(bp)	! port to read from
	cld			! direction is UP
	ret


!*===========================================================================*
!*				p_phys_copy				     *
!*===========================================================================*
p_phys_copy:
	cld
	pop	dx
	pop	_gdt+DS_286_OFFSET+DESC_BASE
	pop	ax		! pop source into base of source descriptor
	movb	_gdt+DS_286_OFFSET+DESC_BASE_MIDDLE,al
	pop	_gdt+ES_286_OFFSET+DESC_BASE
	pop	ax		! pop destination into base of dst descriptor
	movb	_gdt+ES_286_OFFSET+DESC_BASE_MIDDLE,al
	pop	cx		! byte count in bx:cx
	pop	bx
	sub	sp,#4+4+4

	push	di
	push	si
	push	es
	push	ds
	sub	si,si		! src offset is now 0 relative to start of seg
	mov	di,si		! and destination offset
	jmp	ppc_next

! It is too much trouble to align the segment bases, so word alignment is hard.
! Avoiding the book-keeping for alignment may be good anyway.

ppc_large:
	push	cx
	mov	cx,#0x8000	! copy a large chunk of this many words
	rep
	movs
	pop	cx
	dec	bx
	pop	ds		! update the descriptors
	incb	_gdt+DS_286_OFFSET+DESC_BASE_MIDDLE
	incb	_gdt+ES_286_OFFSET+DESC_BASE_MIDDLE
	push	ds
ppc_next:
	mov	ax,#DS_286_SELECTOR	! (re)load the selectors
	mov	ds,ax
	mov	ax,#ES_286_SELECTOR
	mov	es,ax
	test	bx,bx
	jnz	ppc_large

	shr	cx,#1		! word count
	rep
	movs			! move any leftover words
	rcl	cx,#1		! restore old bit 0
	rep
	movb			! move any leftover byte
	pop	ds
	pop	es
	pop	si
	pop	di
	jmp	(dx)

!*===========================================================================*
!*				p_reset					     *
!*===========================================================================*
! Reset the system by loading IDT with offset 0 and interrupting.

p_reset:
	lidt	idt_zero
	int	3		! anything goes, the 286 will not like it


!*===========================================================================*
!*				p_level0				     *
!*===========================================================================*
! PUBLIC void level0(void (*func)(void))
! Call a function at permission level 0.  This allows kernel tasks to do
! things that are only possible at the most privileged CPU level.
!
p_level0:
	mov	bx, sp
	mov	ax, 2(bx)
	mov	_level0_func, ax
	int	LEVEL0_VECTOR
	ret


!*===========================================================================*
!*				data					     *
!*===========================================================================*
	.data
patch_table:			! pairs (old function, new function)
#if ENABLE_BIOS_WINI
	.data2	_bios13, p_bios13
#endif
	.data2	_cp_mess, p_cp_mess
	.data2	_phys_copy, p_phys_copy
	.data2	portio_setup, p_portio_setup
	.data2	_reset, p_reset
	.data2	_level0, p_level0
	.data2	_restart, p_restart	! in mpx file
	.data2	save, p_save	! in mpx file
end_patch_table:		! end of table

idt_vectors:			! limit and base of real mode interrupt vectors
	.data2	0x3FF
idt_zero:			! zero limit IDT to cause a processor shutdown
	.data2	0, 0, 0

	.bss
save_sp:			! place to put sp when switching to real mode
	.space	2
msw:				! saved real mode machine status word
	.space	2

⌨️ 快捷键说明

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