home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
msvp98b1.lzh
/
MSNUT1.ORG
< prev
next >
Wrap
Text File
|
1993-05-14
|
12KB
|
585 lines
NAME MSNUT1
; File MSNUT1.ASM
; Provides various Intel 8088 level operations, including
; display facilities (via msg buffer or DOS) for char, strings, etc.
;
; Copyright 1991, University of Waterloo.
; Copyright (C) 1985, 1992, Trustees of Columbia University in the
; City of New York. Permission is granted to any individual or institution
; to use this software as long as it is not sold for profit. This copyright
; notice must be retained. This software may not be included in commercial
; products without written permission of Columbia University.
;
; Written by Erick Engelke of the University of Waterloo, Waterloo,
; Ontario, Canada,
; and by Joe R. Doupnik, Utah State University,
; jrd@cc.usu.edu, jrd@usu.Bitnet.
;
; Edit history
; 6 Sept 1991 v3.11
; Last Edit
; 2 Feb 1992
cr equ 0dh
lf equ 0ah
conout equ 2
dos equ 21h
BIOSCLK equ 046ch
HI_MAX equ 018h
LO_MAX equ 0b0h
_TEXT SEGMENT WORD PUBLIC 'CODE'
_TEXT ENDS
_DATA SEGMENT WORD PUBLIC 'DATA'
_DATA ENDS
CONST SEGMENT WORD PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT WORD PUBLIC 'BSS'
_BSS ENDS
DGROUP GROUP CONST, _BSS, _DATA
ASSUME CS: _TEXT, DS: DGROUP, SS: DGROUP
_DATA SEGMENT
extrn _doslevel:word, _msgcnt:word, _msgbuf:byte,_display_mode:byte
_DATA ENDS
_TEXT segment
; Compute 1's-complement sum of data buffer
; unsigned checksum( unsigned word *buf, unsigned cnt)
public _checksum
_checksum proc near
push bp
mov bp,sp
push si
push bx
push cx
push dx
mov si,[bp+4+0] ; offset of data to be checked
mov cx,[bp+4+2] ; cx = cnt
mov bl,cl
shr cx,1 ; group into words
xor dx,dx ; set checksum to 0
cld
jcxz chk3
clc
chk1: lodsw
adc dx,ax
loop chk1
; resolve remainder
chk2: adc dx,0
jc chk2
chk3: and bl,1
jz chk5
xor ah,ah
lodsb
clc
add dx,ax
chk4: adc dx,0
jc chk4
chk5: mov ax,dx ; result into ax
or ax,ax
jnz chk6
mov ax,0ffffh
chk6: pop dx
pop cx
pop bx
pop si
pop bp
ret
_checksum endp
; ntohl(longword x) 32 bit network (big endian) to host (little endian)
; htonl(longword x) 32 bit host (little endian) to network (big endian)
; intel(longword x)
; Reverse order of 4 byte groups between big and little endian forms
;
public _intel, _ntohl, _htonl
_intel proc near
_ntohl equ this byte
_htonl equ this byte
push bp
mov bp,sp
mov ax,[bp+4+2]
mov dx,[bp+4+0]
xchg al,ah
xchg dl,dh
pop bp
ret
_intel endp
; ntohs(word x) 16 bit network (big endian) to host (little endian)
; htons(word x) 16 bit host (little endian) to network (big endian)
; intel16(word x)
; Reverse order of 2 byte groups between big and little endian forms
public _intel16, _ntohs, _htons
_intel16 proc near
_ntohs equ this byte
_htons equ this byte
push bp
mov bp,sp
mov ax,[bp+4+0]
xchg al,ah
pop bp
ret
_intel16 endp
; int ourmod(int top, int bottom)
; Perform modulo function on 16 bit quantities
public _ourmod
_ourmod proc near
push bp
mov bp,sp
push bx
mov ax,[bp+4+0] ; top number
mov bx,[bp+4+2] ; bottom number (radix)
xor dx,dx
or bx,bx ; bottom is zero?
jz ourmod1 ; z = yes, return zero
div bx
ourmod1:mov ax,dx ; return remainder
pop bx
pop bp
ret
_ourmod endp
; int ourdiv(int top, int bottom)
; Perform 16 bit integer division
public _ourdiv
_ourdiv proc near
push bp
mov bp,sp
push bx
mov ax,[bp+4+0] ; top
mov bx,[bp+4+2] ; bottom
xor dx,dx
or bx,bx ; divide by zero?
jz outdiv1 ; z = yes, divide by one
div bx
outdiv1:pop bx
pop bp ; quotient is returned in ax
ret
_ourdiv endp
; int ourlmod(long top, int bottom)
; Perform 32 bit integer modulo function
public _ourlmod
_ourlmod proc near
push bp
mov bp,sp
push bx
mov ax,[bp+4+0] ; top lower 16 bits
mov dx,[bp+4+2] ; top upper 16 bits
mov bx,[bp+4+4] ; bottom
or bx,bx ; zero?
jz outlmo1 ; z = yes divide by 2^16 and quit
div bx
outlmo1:mov ax,dx ; return remainder in ax
pop bx
pop bp
ret
_ourlmod endp
; int ourldiv(long top, int bottom)
; Perform 32 bit integer division of 32 bit quotient by 16 bit divisor
public _ourldiv
_ourldiv proc near
push bp
mov bp,sp
push bx
mov ax,[bp+4+0] ; top lower 16 bits
mov dx,[bp+4+2] ; top upper 16 bits
mov bx,[bp+4+4] ; bottom
cmp dx,bx ; about to overflow?
jae ourldiv1 ; ae = yes, return 0xffffh
div bx
xor dx,dx ; clear remainder (high order ret)
pop bx
pop bp ; quotient is returned in dx:ax
ret
ourldiv1:mov ax,0ffffh ; overflow indication
xor dx,dx ; clear high order
pop bx
pop bp
ret
_ourldiv endp
; long ourlmul(long top, int bottom)
; Perform 32 bit integer multiplication of 32 bit multiplicand by 16 bit mult
public _ourlmul
_ourlmul proc near
push bp
mov bp,sp
push bx
push cx
mov ax,[bp+4+2] ; top upper 16 bits
mov bx,[bp+4+4] ; bottom
mul bx
mov cx,ax ; save product (no overflow noted)
mov ax,[bp+4+0] ; top lower 16 bits
mul bx
adc dx,cx ; new upper 16 bits
pop cx
pop bx
mov sp,bp
pop bp ; long product is returned in dx:ax
ret
_ourlmul endp
; void * bcopy(src, dest, count)
; void *dest, *src;
; size_t count;
; copy count bytes from src to dest
public _bcopy
_bcopy proc near
push bp
mov bp,sp
push es
push si
push di
push cx
mov ax,ds ; set to same data segment
mov es,ax
mov si,[bp+4+0] ; offset of source
mov di,[bp+4+2] ; offset of destination
mov cx,[bp+4+4] ; count
cld
push di ; push dest address for return
jcxz bcopy2 ; z = nothing to copy
or di,di ; is destination NULL?
jz bcopy2 ; z = yes, don't do a thing
cmp si,di ; is source after destination?
ja bcopy1 ; a = yes, no overlap problem
je bcopy2 ; e = same place, do nothing
add di,cx ; start at the ends
dec di
add si,cx
dec si
std ; work backward
bcopy1: rep movsb
bcopy2: pop ax ; recover return destination
cld
pop cx
pop di
pop si
pop es
mov sp,bp
pop bp
ret
_bcopy endp
; void * memset(dest, c, count)
; void *dest;
; char c;
; size_t count;
; Store count copies of byte c in destination area dest
public _memset
_memset proc near
push bp
mov bp,sp
push es
push di
push cx
mov ax,ds ; setup data segment
mov es,ax
mov di,[bp+4+0] ; offset of destination
or di,di ; is it NULL?
jz memset1 ; z = yes, don't do a thing
push di ; save dest for return
mov al,[bp+4+2] ; byte of character c
mov ah,al
mov cx,[bp+4+4] ; count
jcxz memset1 ; z = do nothing
cld
shr cx,1
jnc memset2
stosb
memset2:rep stosw
pop ax ; return pointer to destination
memset1:pop cx
pop di
pop es
mov sp,bp
pop bp
ret
_memset endp
; Timer routines - use set_*timeout to receive a clock value which
; can later be tested by calling chk_timeout with
; that clock value to determine if a timeout has
; occurred. chk_timeout returns 0 if NOT timed out.
; Usage: long set_timeout( int seconds );
; long set_ttimeout( int bios_ticks );
; int chk_timeout( long value );
;
; (c) 1990 University of Waterloo,
; Faculty of Engineering,
; Engineering Microcomputer Network Development Office
; version
; 0.1 7-Nov -1990 E. P. Engelke
public _set_ttimeout
_set_ttimeout proc near
push bp
mov bp,sp
push es
xor ax,ax
cwd
mov es,ax
mov ax,[bp+4+0] ; initial Bios clock ticks
pushf ; critical section
cli
add ax,es:[BIOSCLK+0];
adc dx,es:[BIOSCLK+2];
popf ; end critical section
pop es
pop bp
ret
_set_ttimeout endp
public _set_timeout
_set_timeout proc near
push bp
mov bp,sp
push es
push cx
xor ax,ax ; reference low memory
mov es,ax
mov ax,[bp+4+0] ; seconds
xor dx,dx
mov cx,1165
mul cx ; 1165/64 = 18.203...
mov cx,6
tmp: shr dx,1
rcr ax,1
loop tmp
pushf ; critical section
cli
add ax,es:[BIOSCLK+0]
adc dx,es:[BIOSCLK+2]
popf ; end critical section
pop cx
pop es
pop bp
ret
_set_timeout endp
public _chk_timeout
_chk_timeout proc near
push bp
mov bp,sp
push cx
push es
xor ax,ax
mov es,ax
pushf ; critical section
cli
mov cx,es:[BIOSCLK+0]
mov bx,es:[BIOSCLK+2]
popf ; end critical section
pop es
mov ax,[bp+4+0] ; timeout value
mov dx,[bp+4+2]
cmp dx,bx ; if timeout < clock, has expired
jb ret_tru
cmp ax,cx
jbe ret_tru
; may have gone over by one day
sub ax,LO_MAX
sbb dx,HI_MAX
jc ret_fal ; c = nope, timeout is today
; test timeout new values
cmp dx,bx
jb ret_tru
cmp ax,cx
ja ret_fal
ret_tru:mov ax,1 ; say have timed out
pop cx
pop bp
ret
ret_fal:xor ax,ax ; say have not timed out
pop cx
pop bp
ret
_chk_timeout endp
; unsigned long realclock(void)
public _realclock
_realclock proc near ; get Bios time of day dword
push es
xor ax,ax ; reference low memory
mov es,ax
pushf ; critical section
cli
mov ax,es:[BIOSCLK+0] ; return Bios time of day tick count
mov dx,es:[BIOSCLK+2]
popf ; end critical section
pop es
ret
_realclock endp
; void _chkstk()
; Stack checker
; {
; ;
; }
public __chkstk, __aNchkstk
__chkstk proc near ; MSC v5.1
__aNchkstk equ this byte ; MSC v6.00
pop bx ; pop return address
sub sp,ax ; down adjust stack pointer
jmp bx ; return the no-stack way
__chkstk endp
; void
; outch(char ch)
; Sends character to the screen via the msgbuf buffer if operating at
; interrupt level, or via DOS if operating at task level.
public _outch
_outch proc near
push bp
mov bp,sp
push ax
push bx
cmp _display_mode,0 ; quiet screen?
je outch3 ; e = yes
mov al,[bp+4] ; get the character
cmp _doslevel,0 ; at DOS task level?
je outch1 ; e = no
mov ah,conout ; use DOS
push dx
mov dl,al
int dos
pop dx
jmp short outch3
outch1: cmp _msgcnt,256 ; is buffer filled?
ja outch3 ; a = yes, discard this byte
mov bx,_msgcnt
mov _msgbuf[bx],al
inc _msgcnt
outch3: pop bx
pop ax
mov sp,bp
pop bp
ret
_outch endp
; void
; outsn(char * string, int count)
; display counted string
public _outsn
_outsn proc near
push bp
mov bp,sp
push ax
push si
mov si,[bp+4] ; string address
mov cx,[bp+4+2] ; string length
cld
outsn1: lodsb
or al,al
jz outsn2
push ax ; push arg
call _outch
pop ax ; clean stack
loop outsn1
outsn2: pop si
pop ax
mov sp,bp
pop bp
ret
_outsn endp
; void
; outs(char * string)
; display asciiz string
public _outs
_outs proc near
push bp
mov bp,sp
push ax
push si
mov si,[bp+4] ; asciiz string address
cld
outs1: lodsb
or al,al ; terminator ?
jz outs2 ; z = yes
push ax ; push arg
call _outch
pop ax ; clean stack
jmp short outs1
outs2: pop si
pop ax
mov sp,bp
pop bp
ret
_outs endp
; void
; outhex(char c)
; display char in hex
public _outhex
_outhex proc near
push bp
mov bp,sp
push ax
mov ax,[bp+4] ; incoming character
mov cl, 4
shr al, cl
call outh
mov ax,[bp+4]
call outh
pop ax
mov sp,bp
pop bp
ret
; worker for outhex
outh proc near
and al,0fh
cmp al,9
jbe outh1
add al,'A' - '9' - 1
outh1: add al,'0'
push ax
call _outch
pop ax
ret
outh endp
_outhex endp
; output a string of hex chars
; void
; outhexes(char * string, int count )
public _outhexes
_outhexes proc near
push bp
mov bp,sp
push ax
push si ; preserve such things
mov si,[bp+4] ; get string pointer
mov cx,[bp+4+2] ; get char count
cld
outhexs1:lodsb ; read a byte
push cx ; save loop counter
push ax
call _outhex ; display as hex pair
add sp,2 ; clean stack
pop cx
loop outhexs1 ; do count's worth
pop si
pop ax
mov sp,bp
pop bp
ret
_outhexes endp
_TEXT ends
end