home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
msvp98b1.lzh
/
MSNUT1.ASM
< prev
next >
Wrap
Assembly Source File
|
1992-07-04
|
13KB
|
606 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
;[HF]BIOSCLK equ 046ch
;[HF]HI_MAX equ 018h
;[HF]LO_MAX equ 0b0h
HI_MAX equ 262
LO_MAX equ 54784
_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)
extrn _realclock:near ; [HF]
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
;[HF] push es
;[HF] xor ax,ax
;[HF] cwd
;[HF] mov es,ax
;[HF] mov ax,[bp+4+0] ; initial Bios clock ticks
;[HF] pushf ; critical section
;[HF] cli
;[HF] add ax,es:[BIOSCLK+0];
;[HF] adc dx,es:[BIOSCLK+2];
;[HF] popf ; end critical section
;[HF] pop es
call _realclock ;[HF]
add ax,[bp+4+0] ;[HF]
adc dx,0 ;[HF]
pop bp
ret
_set_ttimeout endp
public _set_timeout
_set_timeout proc near
push bp
mov bp,sp
;[HF] push es
;[HF] push cx
;[HF] xor ax,ax ; reference low memory
;[HF] mov es,ax
;[HF] mov ax,[bp+4+0] ; seconds
;[HF] xor dx,dx
;[HF] mov cx,1165
;[HF] mul cx ; 1165/64 = 18.203...
;[HF] mov cx,6
;[HF]tmp: shr dx,1
;[HF] rcr ax,1
;[HF] loop tmp
;[HF] pushf ; critical section
;[HF] cli
;[HF] add ax,es:[BIOSCLK+0]
;[HF] adc dx,es:[BIOSCLK+2]
;[HF] popf ; end critical section
;[HF] pop cx
;[HF] pop es
push bx ;[HF]
push cx ;[HF]
mov ax,[bp+4+0] ;[HF]
xor dx,dx ;[HF]
mov cx,25 ;[HF] sec -> tic (40 msec)
mul cx ;[HF] dx:ax = tic counts
mov bx,ax ;[HF]
mov cx,dx ;[HF] save dx:ax -> cx:bx
call _realclock ;[HF] get current time in tic
add ax,bx ;[HF] add it (long word)
adc dx,cx ;[HF]
pop cx ;[HF]
pop bx ;[HF]
pop bp
ret
_set_timeout endp
public _chk_timeout
_chk_timeout proc near
push bp
mov bp,sp
push cx
;[HF] push es
;[HF] xor ax,ax
;[HF] mov es,ax
;[HF] pushf ; critical section
;[HF] cli
;[HF] mov cx,es:[BIOSCLK+0]
;[HF] mov bx,es:[BIOSCLK+2]
;[HF] popf ; end critical section
;[HF] pop es
call _realclock ;[HF] get current time (dx:ax)
mov cx,ax ;[HF] copy dx:ax -> bx:cx
mov bx,dx ;[HF]
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)
;[HF] public _realclock
;[HF]_realclock proc near ; get Bios time of day dword
;[HF] push es
;[HF] xor ax,ax ; reference low memory
;[HF] mov es,ax
;[HF] pushf ; critical section
;[HF] cli
;[HF] mov ax,es:[BIOSCLK+0] ; return Bios time of day tick count
;[HF] mov dx,es:[BIOSCLK+2]
;[HF] popf ; end critical section
;[HF] pop es
;[HF] ret
;[HF]_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