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

📄 first-dos.s

📁 linux下从网卡远程启动
💻 S
📖 第 1 页 / 共 4 页
字号:
	xor	dx,dx	mov	cl,CON(0x10)	xor	ch,ch	mul	cx			; compute linear buffer address	add	ax,bx	adc	dx,CON(0)	mov	[di],ax			; set dst for read, src for write	mov	[di+2],dl	mov	[di+5],dh	push	es	mov	ax,cs	mov	es,ax	mov	si,CON(rd_gdt)	mov	cx,CON(SECT_SIZE/2)	; copy 512 bytes, e.g. 256 words	mov	ax,CON(0x8700)		; let the BIOS move the sector	int	0x15	pop	es	pop	ax	pop	dx	pop	cx	pop	di	pop	si	ret;====================================================================;; Return a pointer to the disk drive status byte. This routine should; not change any flags!; Input:  none; Output: ES:BX  -  pointer to disk drive status byte; Registers changed: BX, ESgetsts:	mov	bx,CON(BIOS_SEG)	; status byte is in BIOS data	mov	es,bx			; segment	SEGCS	mov	bx,LOC(statof)	ret;====================================================================;; Initialize the XMS interface. This is necessary to prevent the; ram disk from getting overwritten. The way this works is to; first allocate all of the available XMS, then resize the memory; block to end just above the ramdisk and lock it. Unfortunately; we have to do it this complicated because there is no way of; knowing how the XMS is going to allocate the available memory.; Another problem is that at least HIMEM.SYS requires up to 256; bytes of stack, and we cannot assume the caller of INT 13 to; provide that much so we have to change stacks.; Input:  none; Output: none; Registers changed: AX, BXinixms:	call	setstk			; set new stack; First check that the XMS version number is correct. To support all; necessary functions it has to be version 2.0+.	xor	ah,ah	call	callxm			; get version number	cmp	ah,CON(0x02)	jb	inixm8			; wrong XMS version; Determine how much memory we can allocate.	mov	ah,CON(0x08)	xor	bl,bl			; get amount of extended memory	call	callxm	or	bl,bl			; check for error	jnz	inixm8	mov	bx,LOC(rdsize)		; get size of ramdisk	add	bx,BCON(65)		; care for a missing HMA	cmp	bx,ax			; check if enough memory for ram disk	ja	inixm8; Grab all of the extended memory.	push	bx	mov	dx,ax			; grab largest block - which is whole	mov	ah,CON(0x09)		; memory because there should be no	call	callxm			; other process using XMS	pop	bx	or	ax,ax			; check for error	jz	inixm8	mov	LOC(xmshdl),dx		; save handle; Now resize the memory block so that it will contain the ramdisk image.	mov	ah,CON(0x0f)		; reallocate memory block	call	callxm	or	ax,ax			; check for error	jnz	inixm1inixm8:	mov	WLOC(xmshdl),CON(0)	; in case of error dont return handle	JMP(inixm9); Now lock the memory block and check that the physical address of the; memory block is correct.inixm1:	mov	dx,LOC(xmshdl)	mov	ah,CON(0x0c)		; lock memory block	call	callxm	add	bx,CON(0x03ff)	adc	dx,BCON(0x0001)		; add 65kb - maximum difference	sub	bx,LOC(rdaddr+0)	; check that ramdisk address is below	sbb	dx,LOC(rdaddr+2)	jc	inixm8; Thats it. Restore all registers and swap the stack back to its; original state.inixm9:	call	rststk			; restore old stack	ret;====================================================================;; Call XMS driver.; Input:  AH  -  function code;         other registers depending on function code; Output: depends on called function; Registers changed: depends on called functioncallxm:	push	ax	push	bp	push	ax	mov	bp,sp	mov	ax,[bp+6]	mov	[bp+4],ax		; make far return address from	mov	[bp+6],cs		; near call	pop	ax	pop	bp	SEGCS	push	WLOC(xmsadr+2) 		; push address of XMS driver	SEGCS	push	WLOC(xmsadr+0)	retf				; call XMS driver;====================================================================;; Set new stack; Input:  none; Output: none; Registers changed: AX, BX, DS, SS, SPsetstk:	cli	pop	bx			; get return address	mov	ax,sp	SEGCS	mov	LOC(oldstk+0),ax	SEGCS	mov	LOC(oldstk+2),ss	; save old stack pointer	mov	ax,cs	mov	ss,ax	mov	sp,CON(newtos - 2)	; change to new stack	sti	push	cx	push	dx	push	si			; save all registers	push	di	push	es	push	ds	mov	ax,cs			; set DS to current segment	mov	ds,ax	jmp	bx			; return to caller;====================================================================;; Reset stack to old stack; Input:  none; Output: none; Registers changed: all (reset to old state)rststk:	pop	bx			; get return address	pop	ds	pop	es	pop	di	pop	si			; restore all registers	pop	dx	pop	cx	cli	SEGCS	mov	ax,LOC(oldstk+0)	; restore old stack	SEGCS	mov	ss,LOC(oldstk+2)	mov	sp,ax	sti	jmp	bx			; return to caller;====================================================================;; Remove ramdisk from memory. This involves restoring all interrupt; vectors, freeing all used memory and restoring the DOS drive para-; meter table. Since we need to call the XMS drive, we have to switch; stacks like with inixms.; Input:  none; Output: AL  -  non-zero if error; Registers changed: AXrmrd:	push	bx	call	setstk			; set new stack	mov	al,LOC(drvid)	cmp	al,CON(0x80)		; can only restore floppy drives	jb	rmrd1rmrd8:	call	rststk			; return with error	pop	bx	mov	al,CON(0x01)	ret; First determine the address of the DOS disk parameter block for the; ramdisk and check that the open count is zero, i.e. no open file on; the device.rmrd1:	push	ds	mov	ax,CON(0x0803)	int	0x2f			; get address of drive parameter	mov	ax,ds			; table from DOS	mov	es,ax	pop	dsrmrd2:	SEGES	mov	al,[di+4]		; get physical unit number	cmp	al,LOC(drvid)		; is it our drive?	je	rmrd3	cmp	di,CON(0xffff)		; error if we couldnt find the DPB	je	rmrd8			; for the ramdisk	SEGES	les	di,[di]			; get pointer to next entry	JMP(rmrd2)rmrd3:	mov	LOC(dpb_addr+0),di	mov	LOC(dpb_addr+2),es	SEGES	mov	ax,[di+0x20]		; get device open count	or	ax,ax	jnz	rmrd8; Next restore the interrupt vectors. Int 13h is special as it is; redirected by DOS. However, DOS provides a function to restore; that interrupt. Interrupt 2Fh doesnt have to get restored because; DOS does never call the old interrupt again.	xor	ax,ax	mov	es,ax	mov	ax,cs	SEGES				; first check that nobody redirected	cmp	ax,LOC(IF8_INT+2)	; our own interrupts. In that case	jne	rmrd8			; there is no chance of removing the	SEGES				; ramdisk.	mov	ax,LOC(IF8_INT+0)	cmp	ax,CON(intF8)	jne	rmrd8	mov	si,CON(if1sig)	mov	di,CON(IF1_INT)	mov	cx,CON(4)		; interrupt F1h contains a signature	repz				; and no vector	cmpsb	jnz	rmrd8	push	ds	les	bx,LOC(old13h)		; get old interrupt vector 13h	mov	dx,bx	mov	ax,es			; save it into DS:DX and ES:BX	mov	ds,ax	mov	ah,CON(0x13)	int	0x2f			; call DOS to restore vector	mov	ax,ds	mov	cx,cs	cmp	ax,cx			; check that its indeed our interrupt	jne	rmrd4			; which we are replacing	mov	ax,es	cmp	ax,cx	jne	rmrd4	cmp	bx,CON(int13)	jne	rmrd4	cmp	dx,CON(int13)	je	rmrd5rmrd4:	mov	ah,CON(0x13)	int	0x2f			; restore old interrupt	pop	ds			; someone redirected the interrupt#ifdef	USE_AS86	jmp	near rmrd8		; already, cant restore#endif#ifdef	USE_NASM	jmp	rmrd8			; already, cant restore#endifrmrd5:	pop	ds			; restore the other interrupts	cli	xor	ax,ax	mov	es,ax	mov	ax,LOC(oldF8h+0)	SEGES	mov	LOC(IF8_INT+0),ax	mov	ax,LOC(oldF8h+2)	SEGES	mov	LOC(IF8_INT+2),ax	sti; OK, we can now setup the DOS drive parameter table to contain the; correct values for the physical floppy drive. If we couldnt create; a valid parameter table entry for this drive, simply mark the DOS; entry as invalid. This will cause "Not Ready" errors in DOS. This; doesnt work with DR-DOS 5.0!	les	di,LOC(dpb_addr)	; get address of DPB	SEGES#ifdef	USE_AS86	or	[di+0x1f],BCON(80)	; mark drive as invalid#endif#ifdef	USE_NASM	or	word [di+0x1f],BCON(80)	; mark drive as invalid#endif	test	BLOC(dpb_valid),CON(0xff)	; check if DPB valid	jz	rmrd6	cld				; got correct table entry	mov	cx,CON(dpb_end - dpb)	mov	si,CON(dpb)	add	di,BCON(4)	rep	movsb				; simply copy the DPB; Next remove the ramdisk image from extended memory using the XMS driver.rmrd6:	mov	dx,LOC(xmshdl)	or	dx,dx			; only free memory if we really	jz	rmrd7			; assigned it with XMS	push	dx	mov	ah,CON(0x0d)	call	callxm			; unlock memory block	pop	dx	or	ax,ax			; dont free block if error	jz	rmrd7	mov	ah,CON(0x0a)	call	callxm			; free memory block; Finally we can remove the memory for the ramdisk driver. We only; reset the owner field of the memory control block to 0 to indicate; it as free.rmrd7:	mov	dx,CON(start_resident)	; determine last usable segment	mov	cl,CON(4)		; from segment and offset of	shr	dx,cl			; the resident section	mov	ax,cs	add	dx,ax			; add offset to segment	sub	dx,BCON(2)	mov	es,dx	mov	di,CON(1)	xor	ax,ax			; set owner field to 0	stosw	add	di,BCON(5)	mov	cx,CON(4)		; clear owner name	rep	stosw; Thats it. Return to caller.rmrd9:	call	rststk			; restore old stack	pop	bx	xor	al,al			; return without error	ret;====================================================================;; Variables for the resident section		ALIGN(2)oldints:old13h:		dd	0		; old interrupt 13h vectorold2Fh:		dd	0		; old interrupt 2Fh vectoroldF1h:		dd	0		; old interrupt F1h vectoroldF8h:		dd	0		; old interrupt F8h vector; Disk parameters for ram diskstatof:		dw	BIOS_FDSTAT	; offset to BIOS disk status byterdaddr:		dd	0		; base address of ram diskrdsize:		dw	0		; size of ram disk in kbcylnum:		dw	80		; number of cylinderssecnumlo:	dw	2400		; number of sectors on disksecnumhi:	dw	0secptk:		dw	15		; number of sectors per trackheads:		db	1		; number of headsdrvnum:		db	1		; number of disk drivesdrvid:		db	0		; ram disk drive idnohd:		db	0		; no-hard-disk flagsyscnf:		dw	0		; system configuration from BIOS		ALIGN(2); Variables used to access the XMS interfacexmshdl:		dw	0		; XMS handle for ram diskxmsadr:		dd	0		; address of XMS driver interface; Variables used to redirect the stackoldstk:		dd	0		; old stack pointernewstk:		SPACE(512)		; new stack for calling XMS drivernewtos:					; new top of stack; Signature to put into interrupt vector F1hif1sig:		STRDECL('NetB')	ALIGN(16)			; has to be paragraph aligned; Descriptor table to access ram disk using the BIOSrd_gdt:		dw	0,0,0,0		dw	0,0,0,0rd_src:		dw	0xffff		; lengthrd_srcb:	db	0,0,0		; base		db	0x93		; typebyte		db	0		; limit16 =0rd_srcbh:	db	0		; base24rd_dst:		dw	0xffff		; lengthrd_dstb:	db	0,0,0		; base		db	0x93		; typebyte		db	0		; limit16 =0rd_dstbh:	db	0		; base24		dw	0,0,0,0		; BIOS CS		dw	0,0,0,0		; BIOS DS; DOS disk parameter block. It contains the definitions for the; floppy disk drive which is redirected by the ramdisk, and used; for removing the ramdisk drive. Note that this DPB is only; valid for DOS 4.0 and higher.dpb_addr:	dd	0		; address of DPB in DOS data areadpb_valid:	db	0		; non-zero if DPB is validdpb:dpb_phys:	db	0		; BIOS ID of physical drivedpb_log:	db	0		; logical DOS drive IDdpb_bpb_low:	dw	512		; BIOS param block for lowest capacity		db	0xff		dw	1		db	2		dw	64		dw	360		db	0x00		dw	2		dw	9		dw	1		dd	0		dd	0dpb_fat:	db	0		; flag indicating 16-bit FATdpb_open:	dw	0		; device open countdpb_type:	db	0x01		; device typedpb_flags:	dw	DPB_F_DEFAULT	; flags describing drivedpb_cyls:	dw	80		; number of cylindersdpb_bpb_cur:	dw	512		; BIOS parameter block for current		db	1		dw	1		db	2		dw	224		dw	2400		db	0xf9		dw	7		dw	15		dw	2		dd	0		dd	0dpb_rsvd:	db	0, 0, 0, 0, 0, 0dpb_ltrack:	db	0xff		; last accessed trackdpb_lacc:	dd	0xffffffff	; time of last disk accessdpb_volname:	STRDECL('NO NAME    ')	; volume name		db	0dpb_sernum:	dd	0		; volume serial numberdpb_fsname:	STRDECL('FAT12   ')	; file system name		db	0dpb_end:; Copy of bootp block from bootrom. This has to be last in the data area!btplen:		dw	0		; length of bootp blockbtpnew:					; bootp block has to be at the very end_end:		SPACE(4096-(_end-_start))

⌨️ 快捷键说明

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