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

📄 pcgen.s

📁 用于底层开发的TCPIP协议栈源代码
💻 S
📖 第 1 页 / 共 2 页
字号:
kbraw	endp

; Clock tick interrupt handler. Note the use of "label" rather than "proc"
; here, necessitated by the fact that "proc" automatically generates BP-saving
; code that we don't want here.

	public	btick
	label	btick	far

	pushf
	cld
	push	ds
	cli
	mov	ds,cs:dbase	; establish interrupt data segment

	mov	Sssave,ss	; stash user stack context
	mov	Spsave,sp

	mov	ss,cs:dbase
	lea	sp,Stktop

	PUSHALL
	push	es

	call	ctick

 	pop	es
	POPALL
	mov	ss,Sssave
	mov	sp,Spsave	; restore original stack context
	pop	ds
	POPFLAGS
	jmp	dword ptr [toff]		; link to previous vector

; Convert 32-bit int in network order to host order (dh, dl, ah, al)
; Called from C as
; int32 get32(char *cp);

	public	get32
get32	proc
	arg	cp:ptr
	if	@Datasize NE 0
		uses	ds,si
		lds	si,cp	; ds:si = cp
	else
		uses	si
		mov	si,cp	; ds:si = cp (ds already set)
	endif

	cld
	lodsw
	mov	dh,al	; high word to dx, a-swapping as we go
	mov	dl,ah
	lodsw
	xchg	al,ah	; low word stays in ax, just swap
	ret
get32	endp

; Convert 16-bit int in network order to host order (ah, al)
; Called from C as
; int16 get16(char *cp);

	public	get16
get16	proc
	arg	cp:ptr
	if	@Datasize NE 0
		uses	ds,si
		lds	si,cp	; ds:si = cp
	else
		uses	si
		mov	si,cp	; ds:si = cp (ds already set)
	endif

	lodsw		; note: direction flag is don't-care
	xchg	al,ah	; word stays in ax, just swap
	ret
get16	endp

; Convert 32-bit int to network order, returning new pointer
; Called from C as
; char *put32(char *cp,int32 x);

	public	put32
put32	proc
	arg	cp:ptr,x:dword
	if	@Datasize NE 0
		uses	ds,di
		les	di,cp	; es:di = cp
		mov	ax,ss	; our parameter is on the stack, and ds might not
		mov	ds,ax	;   be pointing to ss.
	else
		uses	di
		mov	di,cp	; es:di = cp
		mov	ax,ds	; point es at data segment
		mov	es,ax
	endif

	cld
	mov	ax,word ptr (x+2)	; read high word of machine version
	xchg	ah,al			; swap bytes
	stosw				; output in network order
	mov	ax,word ptr x		; read low word of machine version
	xchg	ah,al			; swap bytes
	stosw				; put in network order

	mov	ax,di	; return incremented output pointer
	if	@Datasize NE 0
		mov	dx,es	; upper half of pointer
	endif
	ret
put32	endp

; Convert 16-bit int to network order, returning new pointer
; Called from C as
; char *put16(char *cp,int16 x);

	public	put16
put16	proc
	arg	cp:ptr,x:word
	uses	di
	if	@Datasize NE 0
		les	di,cp	;es:di = cp
	else
		mov	di,cp	; es:di = cp
		mov	ax,ds
		mov	es,ax
	endif
	cld
	mov	ax,x	; fetch source word in machine order
	xchg	ah,al	; swap bytes
	stosw		; save in network order
	mov	ax,di	; return new output pointer to user
	if	@Datasize NE 0
		mov	dx,es	; upper half of pointer
	endif
	ret
put16	endp

if	@CPU AND 2
; fast I/O buffer routines
; version for 80[1234]86 (uses ins, outs instructions)

; outbuf - put a buffer to an output port
	public	outbuf
outbuf	proc
	arg	port:word,buf:ptr,cnt:word
	if	@Datasize NE 0
		uses	ds,si
		lds	si,buf	; ds:si = buf
	else
		uses	si
		mov	si,buf	;ds:si = buf (ds already set)
	endif
	mov	dx,port
	mov	cx,cnt
	cld
	rep outsb		; works only on PC/AT (80286)
	mov	dx,ds
	mov	ax,si		; return pointer just past end of buffer
	ret
outbuf	endp

; inbuf - get a buffer from an input port
	public	inbuf
inbuf	proc
	arg	port:word,buf:ptr,cnt:word
	uses	di
	if	@Datasize NE 0
		les	di,buf		; es:di = buf
	else
		mov	di,buf		; es:di = buf
		mov	ax,ds
		mov	es,ax
	endif
	mov	dx,port
	mov	cx,cnt
	cld
	rep insb		; works only on PC/AT (80286)
	mov	dx,es
	mov	ax,di		; return pointer just past end of buffer
	ret
inbuf	endp

else

; fast buffer I/O routines
; version for 8086/8

; outbuf - put a buffer to an output port
	public	outbuf
outbuf	proc
	arg	port:word,buf:ptr,cnt:word
	if	@Datasize NE 0
		uses	ds,si
		lds	si,buf	; ds:si = buf
	else
		uses	si
		mov	si,buf	; ds:si = buf (ds already set)
	endif

	mov	dx,port
	mov	cx,cnt
	cld

; If buffer doesn't begin on a word boundary, send the first byte
	test	si,1	; (buf & 1) ?
	jz	@@even ; no
	lodsb		; al = *si++;
	out	dx,al	; out(dx,al);
	dec	cx	; cx--;
	mov	cnt,cx	; save for later test
@@even:
	shr	cx,1	; cx = cnt >> 1; (convert to word count)
; Do the bulk of the buffer, a word at a time
	jcxz	@@nobuf	; if(cx != 0){
@@deloop:
	lodsw		; do { ax = *si++; (si is word pointer)
	out	dx,al	; out(dx,lowbyte(ax));
	mov	al,ah
	out	dx,al	; out(dx,hibyte(ax));
	loop	@@deloop	; } while(--cx != 0); }
; now check for odd trailing byte
@@nobuf:
	mov	cx,cnt
	test	cx,1
	jz	@@cnteven
	lodsb		; al = *si++;
	out	dx,al
@@cnteven:
	mov	dx,ds
	mov	ax,si		; return pointer just past end of buffer
	ret
outbuf	endp

; inbuf - get a buffer from an input port
	public	inbuf
inbuf	proc
	arg port:word,buf:ptr,cnt:word
	uses	di
	if	@Datasize NE 0
		les	di,buf	; es:di = buf
	else
		mov	di,buf	; es:di = buf
		mov	ax,ds
		mov	es,ax
	endif
	mov	dx,port
	mov	cx,cnt
	cld

; If buffer doesn't begin on a word boundary, get the first byte
	test	di,1	; if(buf & 1){
	jz	@@bufeven ;
	in	al,dx	; al = in(dx);
	stosb		; *di++ = al
	dec	cx	; cx--;
	mov	cnt,cx	; cnt = cx; } save for later test
@@bufeven:
	shr	cx,1	; cx = cnt >> 1; (convert to word count)
; Do the bulk of the buffer, a word at a time
	jcxz	@@nobuf	; if(cx != 0){
@@deloop:
	in	al,dx	; do { al = in(dx);
	mov	ah,al
	in	al,dx	; ah = in(dx);
	xchg	al,ah
	stosw		; *si++ = ax; (di is word pointer)
	loop	@@deloop	; } while(--cx != 0);
; now check for odd trailing byte
@@nobuf:
	mov	cx,cnt
	test	cx,1
	jz	@@cnteven
	in	al,dx
	stosb		; *di++ = al
@@cnteven:
	mov	dx,es
	mov	ax,di		; return pointer just past end of buffer
	ret
inbuf	endp

endif

	public	longdiv

; long unsigned integer division - divide an arbitrary length dividend by
; a 16-bit divisor. Replaces the dividend with the quotient and returns the
; remainder. Called from C as
;
; unsigned short
; longdiv(unsigned short divisor,int cnt,unsigned short *dividend);
;
;Register usage:
; di - divisor
; si - pointer into dividend array
; cx - loop counter, initialized to the number of 16-bit words in the dividend
; ax - low word of current dividend before each divide, current quotient after
; dx - remainder from previous divide carried over, becomes high word of
;      dividend for next divide

longdiv	proc
	arg	divisor:word,cnt:word,dividend:ptr
	if	@Datasize NE 0
		uses	ds,si,di
		lds	si,dividend
	else
		uses	si,di
		mov	si,dividend	;si -> dividend array
	endif

	cmp	divisor,0		; divisor == 0?
	jne	@2			; no, ok
	xor	ax,ax			; yes, avoid divide-by-zero trap
	jmp	short @1

@2:	mov	dx,0			; init remainder = 0
	mov	cx,cnt			; init cnt
	mov	di,divisor		; cache divisor in register

@@deloop:
	mov	ax,word ptr [si]	; fetch current word of dividend
	cmp	ax,0			; dividend == 0 ?
	jne	@7			; nope, must do division
	cmp	dx,0			; remainder also == 0?
	je	@4			; yes, skip division, continue

@7:	div	di			; do division
	mov	word ptr [si],ax	; save quotient

@4:	inc	si			; next word of dividend
	inc	si
	loop 	@@deloop

	mov	ax,dx			; return last remainder
@1:	ret

longdiv	endp

; long unsigned integer multiplication - multiply an arbitrary length
; multiplicand by a 16-bit multiplier, leaving the product in place of
; the multipler, returning the carry. Called from C as
;
; unsigned short
; longmul(unsigned short multiplier,int cnt,unsigned short *multiplier);
;
; Register usage:
; di = multiplier
; si = pointer to current word of multiplicand
; bx = carry from previous round
; cx = count of words in multiplicand
; dx,ax = scratch for multiply

	public longmul
longmul	proc	far
	arg	multiplier:word,n:word,multiplicand:ptr
	if	@Datasize NE 0
		uses	ds,si,di
		lds	si,multiplicand
	else
		uses	si,di
		mov	si,multiplicand	; si -> multiplicand array
	endif

	mov	di,multiplier		; cache multiplier in register
	xor	bx,bx			; init carry = 0
	mov	cx,n			; fetch n
	mov	ax,cx
	shl	ax,1			; *2 = word offset
	add	si,ax			; multiplicand += n

@@deloop:
	dec	si
	dec	si			; work from right to left
	mov	ax,word ptr [si]	; fetch current multiplicand
	or	ax,ax			; skip multiply if zero
	jz	@@nomult
	mul	di			; dx:ax <- ax * di
@@nomult:
	add	ax,bx			; add carry from previous multiply
	mov	word ptr [si],ax	; save low order word of product
	mov	bx,0			; clear previous carry, leaving CF alone
	adc	bx,dx			; save new carry
	xor	dx,dx			; clear in case we skip the next mult
	loop	@@deloop

	mov	ax,bx			; return final carry
	ret
longmul	endp

ifdef	notdef
; divide 32 bits by 16 bits, returning both quotient and remainder
; This allows C programs that need both to avoid having to do two divisions
;
; Called from C as
;	long divrem(dividend,divisor)
;	long dividend;
;	short divisor;
;
;	The quotient is returned in the low 16 bits of the result,
;	and the remainder is returned in the high 16 bits.

	public	divrem
divrem	proc
	arg	dividend:dword,divisor:word
	mov	ax,word ptr dividend
	mov	dx,word ptr (dividend+2)
	div	divisor
	ret
divrem	endp
endif	

; General purpose hash function for IP addresses
; Uses lookup table Hashtab[] initialized in iproute.c
; Called from C as
; char hash_ip(int32 ipaddr);

	public hash_ip
hash_ip	proc
	arg	ipaddr:dword
	lea	bx,Hashtab
	mov	ax,word ptr ipaddr
	xor	ax,word ptr (ipaddr+2)
	xor	al,ah
	xlat
	xor	ah,ah
	ret
hash_ip	endp

; Compute int(log2(x))
; Called from C as
; int ilog2(int16 x);

	public	ilog2
ilog2	proc
	arg	x:word
	mov	cx,16
	mov	ax,x
@@2:	rcl	ax,1 
	jc	@@1
	loop	@@2
@@1:	dec	cx
	mov	ax,cx
	ret
ilog2	endp
	end

⌨️ 快捷键说明

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