📄 pcgen.s
字号:
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 + -