dos_compilers/Manx Aztec C86 v42b/ARC/MCH86.ARC
2024-07-02 07:07:59 -07:00

2227 lines
32 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

makefile
OBJ=csav.o farcall.o fcall.o index.o lsubs.o memccpy.o memchr.o memcmp.o\
memcpy.o memset.o movblock.o movmem.o peek.o pointers.o port.o ptradd.o\
ptrdiff.o rindex.o segread.o setjmp.o setmem.o strcat.o strchr.o strcmp.o\
strcpy.o strlen.o strncpy.o strrchr.o swapmem.o sysint.o toupper.o\
cswit.o clswit.o fptrs.o fltstub.o strstr.o stricmp.o strlwr.o strrev.o
CC=cc
AS=as
MODEL=
AMODEL=0
DIR=
.c.o:
$(CC) +$(MODEL) -n $*.c -o $@
sqz $@
.asm.o:
$(AS) -dMODEL=$(AMODEL) $*.asm -o $@
sqz $@
bld: $(OBJ) cswt.o olsubs.o
@echo mch86 done
bldlc bldl bldld: $(OBJ)
@echo mch86 done
$(DIR)$(MODEL)rom.o: rom.asm
$(AS) -dMODEL=$(AMODEL) rom.asm -o $@
ovly: $(DIR)ovld.o $(DIR)ovldpath.o $(DIR)ovbgn.o
@echo overlay done
ovlyl ovlyld ovlylc:
@echo overlays supported only in small model
$(DIR)ovld.o: ovloader.c
$(CC) +$(MODEL) -n ovloader.c -o $@
$(DIR)ovldpath.o: ovloader.c
$(CC) +$(MODEL) -n -DDOS20 ovloader.c -o $@
$(DIR)ovbgn.o: ovbgn.asm
$(AS) -dMODEL=$(AMODEL) ovbgn.asm -o $@
clswit.asm
; Copyright (C) 1983, 85 by Manx Software Systems
; :ts=8
include lmacros.h
public $clswt
$clswt proc
pop bx ; get address of table
ifdef FARPROC
pop es
endif
push di
push si
mov si,bx ; save base address
dec cx
mov di,cx ; save number of entries in di
ltop:
ifdef FARPROC
cmp ax,es:word ptr [bx]
jne notit
cmp dx,es:word ptr 2[bx]
je found
else
cmp ax,cs:word ptr [bx]
jne notit
cmp dx,cs:word ptr 2[bx]
je found
endif
notit:
add bx,4
loop ltop
found:
shl di,1
shl di,1 ; adjust di for length of values
add di,si ; di now points at array of labels
sub bx,si ; find which entry matched
shr bx,1 ; divide by 2 to get offset to label
ifdef FARPROC
mov ax,es:word ptr [di][bx] ; get address to return to
pop si
pop di
push es
push ax
ret
else
mov ax,cs:word ptr [di][bx] ; get address to return to
pop si
pop di
jmp ax
endif
$clswt endp
finish
end
csav.asm
; Copyright (C) 1983 by Manx Software Systems
; :ts=8
include lmacros.h
dataseg segment para public 'data'
extrn _sbot_:word
extrn _lowwater_:word
dataseg ends
assume ds:dataseg,cs:codeseg
ifdef FARPROC
extrn _stkover_:far
else
extrn _stkover_:near
endif
extrn $begin:far
dw near ptr $begin
public $csav, $cret
$csav proc
pop bx
ifdef FARPROC
pop dx
endif
push bp
mov bp,sp
add sp,ax
cmp sp,bp ;check for wrap around
ja stackfault
cmp sp,word ptr _sbot_ ;or moving into the RED zone
jb stackfault
cmp sp,word ptr _lowwater_
ja nodeeper
mov word ptr _lowwater_,sp
nodeeper:
push di
push si
ifdef FARPROC
push cs
mov ax,offset $cret
push ax
push dx
push bx
ret
else
call bx
endif
$csav endp
$cret proc
pop si
pop di
mov sp,bp
pop bp
ret
$cret endp
stackfault:
mov sp,bp ;put stack back the way it was
jmp _stkover_
finish
end
cswit.asm
; Copyright (C) 1983, 85 by Manx Software Systems
; :ts=8
include lmacros.h
public $cswt
$cswt proc
ifndef FARPROC
pop bx ; get address of table
push di
ifndef LONGPTR
push es
endif
mov di,cs
mov es,di
mov di,bx ; make di to point to table of values
mov bx,cx ; save number of entries in bx
shl bx,1 ; adjusted for size of an entry
cld
repne scasw ; find the right entry
mov cx,es:word ptr -4[di][bx] ; pick up target address
ifndef LONGPTR
pop es
endif
pop di
jmp cx ; jump there
endif
$cswt endp
finish
end
cswt.asm
; Copyright (C) 1983, 85 by Manx Software Systems
; :ts=8
include lmacros.h
ifdef FARPROC
data equ word ptr es:[bx]
addr equ word ptr es:2[bx]
dflt equ word ptr es:[bx]
else
data equ word ptr cs:[bx]
addr equ word ptr cs:2[bx]
dflt equ word ptr cs:[bx]
endif
slot equ 4
public $swt
$swt proc
pop bx
ifdef FARPROC
ifndef LONGPTR
mov dx,es
endif
pop es
push es
endif
mov cx,data
add bx,2
jcxz eswt
swtloop:
cmp ax,data
je found
add bx,slot
loop swtloop
eswt:
push dflt
ifdef FARPROC
ifndef LONGPTR
mov es,dx
endif
endif
ret
found:
push addr
ifdef FARPROC
ifndef LONGPTR
mov es,dx
endif
endif
ret
$swt endp
finish
end
farcall.asm
; :ts=8
;Copyright (C) 1983, 85 by Manx Software Systems
include lmacros.h
procdef farcall, <<where,dword>, <srcregs,ptr>, <dstregs,ptr>>
push si
push di
push ds
push es
;
ldptr bx,srcregs,ds
mov ax,[bx]
push 2[bx] ;save BX value for later
mov cx,4[bx]
mov dx,6[bx]
mov si,8[bx]
mov di,10[bx]
mov es,14[bx]
mov ds,12[bx] ;trash DS last
pop bx ;now get value for BX
push bp
call where
pop bp
push ds ;save returned DS
push bx ;save returned BX
mov ds,-6[bp] ;fetch C's data seg, for small model
ldptr bx,dstregs,ds
mov [bx],ax
pop 2[bx] ;value returned in BX
mov 4[bx],cx
mov 6[bx],dx
mov 8[bx],si
mov 10[bx],di
pop 12[bx] ;value returned in DS
mov 14[bx],es
pop es
pop ds
pop di
pop si
pop bp
pushf
pop ax
ret
pend farcall
finish
end
fcall.asm
; Copyright (C) 1985 by Manx Software Systems
; :ts=8
largecode
codeseg segment byte public 'code'
assume cs:codeseg
public $fcall
$fcall proc far
push dx
push ax
ret
$fcall endp
codeseg ends
end
fltstub.asm
; Copyright (C) 1987 by Manx Software Systems, Inc.
; :ts=8
include lmacros.h
public $fltinit
$fltinit proc
clc ;all OK
ret
$fltinit endp
finish
end
fptrs.asm
; :ts=8
;Copyright (C) 1985 by Manx Software Systems
include lmacros.h
assume ds:dataseg
internal $fptrs
;
; $hdiff ; subtract (and compare) huge pointers in ax:dx cx:bx
;
intrdef $hdiff
push si
sub dx,bx
sbb si,si
mov bx,cx
mov cx,4
sloop: shl dx,1
rcl si,1
loop sloop
add ax,dx
adc si,0
sub ax,bx
sbb si,0
mov dx,si
pop si
cmp dx,0
jnz doret
cmp ax,0
jz outnow
outclear:
clc
ret
doret:
jgt outclear
stc
outnow:
ret
intrdef $hadd ; add hugeptr in cx:bx with long in ax:dx
push si
push di
mov si,cx
mov cx,4
xor di,di
addloop:
shl bx,1
rcl di,1
loop addloop
add bx,si
adc di,0
add ax,bx
adc di,dx
mov cx,4
mov dx,ax
and ax,0fh
canon:
shr di,1
rcr dx,1
loop canon
pop di
pop si
ret
intrdef $hinx ;add hugeptr in cx:bx to long in ax:dx and put in es:bx
push si
push di
mov si,cx
mov cx,4
xor di,di
xddloop:
shl bx,1
rcl di,1
loop xddloop
add bx,si
adc di,0
add bx,ax
adc di,dx
mov cx,4
mov ax,bx
and bx,0fh
xcanon:
shr di,1
rcr ax,1
loop xcanon
mov es,ax
pop di
pop si
ret
$fptrs endp
finish
end
index.asm
; :ts=8
;Copyright (C) 1983 by Manx Software Systems
include lmacros.h
procdef index, <<arg,ptr>,<val,byte>>
cld
push si
pushds
ldptr si,arg,ds
mov bl,val
lookloop:
lodsb
test al,al
jz notfound
cmp al,bl
jne lookloop
retptrr si,ds
dec ax
popds
pop si
pret
notfound:
retnull
popds
pop si
pret
pend index
finish
end
lsubs.asm
; Copyright (C) 1983 1984 by Manx Software Systems
; :ts=8
include lmacros.h
internal $longs
;
intrdef $ldv
;long divide (primary = primary/secondary)
push di
sub di,di ;mark result as positive
test dx,dx
jns prim_ok
neg dx
neg ax
sbb dx,0
inc di ;mark as negative
prim_ok:
test bx,bx
jns sec_ok
neg bx
neg cx
sbb bx,0
xor di,1 ;flip sign of result
sec_ok:
call comdivide
chksign:
test di,di
jz posres
neg dx
neg ax
sbb dx,0
posres:
pop di
ret
;
intrdef $lrm
;long remainder (primary = primary%secondary)
push di
mov di,0 ;mark result as positive
test dx,dx
jns rprim_ok
neg dx
neg ax
sbb dx,0
inc di ;mark as negative
rprim_ok:
test bx,bx
jns rsec_ok
neg bx
neg cx
sbb bx,0
rsec_ok:
call comdivide
mov ax,cx
mov dx,bx
jmp chksign
;
intrdef $lum
;unsigned long remainder (primary = primary%secondary)
call comdivide
mov ax,cx
mov dx,bx
ret
;
intrdef $lud
;unsigned long divide (primary = primary/secondary)
ifdef FARPROC
call comdivide
ret
endif
; fall thru into common divide routine if not large code model
;
comdivide proc near ; divide (dx,ax) by (bx,cx):
; returns quotient in (dx,ax)
; remainder in (bx,cx)
;
test bx,bx ;check for easy case
jnz hardldv
cmp cx,dx
ja veryeasy
push ax
mov ax,dx
sub dx,dx
div cx
mov bx,ax ;save high word of quotient
pop ax
div cx
mov cx,dx ;save remainder
mov dx,bx
sub bx,bx
ret
veryeasy:
div cx
mov cx,dx ;save remainder
mov dx,bx ;bx is already zero if we are here
ret
hardldv:
push di
push si
mov si,cx ;copy divisor (bx,cx) into (di,si)
mov di,bx
push dx ;save dividend for remainder calculation
push ax
test bh,bh
jz shiftit
mov cl,ch ;shift bx,cx right 8 bits
mov ch,bl
mov bl,bh
mov al,ah ;shift dx,ax right 8 bits
mov ah,dl
mov dl,dh
sub dh,dh
shiftit:
shr dx,1
rcr ax,1
shr bl,1
rcr cx,1
test bl,bl
jnz shiftit
div cx ;guess at quotient (may off by 1)
mov cx,ax
; compute remainder = dividend - divisor*quotient
mul si
mov bx,dx
push ax ;save low half
mov ax,cx
mul di
add bx,ax
jnc normal_path
dec cx
pop ax ; delete top element off the stack
mov ax,cx
mul di
mov bx,ax ; save the answer into bx
mov ax,cx
mul si
add bx,dx
mov es,cx ; es now contains the answer of the divide
mov cx,ax
; bx:cx now contains result * quotient
pop ax
pop dx
sub cx,ax
sbb bx,dx
not cx
not bx
add cx,1
adc bx,0
mov ax,es
jmp answer_ok
normal_path:
mov dx,bx ;high half
mov ax,cx ;restore quotient to ax for return
pop bx ;low half of divisor*quotient
pop cx ;low half of dividend
sub cx,bx
pop bx ;high half of dividend
sbb bx,dx
jnc answer_ok ;if we get a borrow, answer was too big
add cx,si ;so adjust the remainder
adc bx,di
dec ax ;and the quotient
answer_ok:
sub dx,dx
pop si
pop di
ret
comdivide endp
$longs endp
finish
end
memccpy.asm
; Copyright (C) 1984, 1985 by Manx Software Systems, Inc.
; :ts=8
include lmacros.h
procdef memccpy,<<s1,ptr>,<s2,ptr>,<char,byte>,<lim,word>>
push si
push di
pushds
cld
ifndef LONGPTR
mov di,ds
mov es,di
endif
ldptr di,s1
ldptr si,s2
mov bl,char
mov cx,lim
jcxz cpydone
cpyloop:
lodsb
stosb
cmp al,bl
jz cpyfnd
loop cpyloop
jmp short cpydone
cpyfnd:
retptrr di,es
popds
pop di
pop si
pret
cpydone:
retnull
popds
pop di
pop si
pret
pend memccpy
finish
end
memchr.asm
; Copyright (C) 1984 by Manx Software Systems
; :ts=8
include lmacros.h
procdef memchr,<<area,ptr>,<char,byte>,<lim,word>>
push di
ifdef LONGPTR
mov ax,ds
mov es,ax
endif
cld
ldptr di,area
mov al,char
mov cx,lim
jcxz notfound
repne scasb
jne notfound
dec di
retptrr di,es
pop di
pret
notfound:
retnull
pop di
pret
pend memchr
finish
end
memcmp.asm
; Copyright (C) 1984, 1985 by Manx Software Systems, Inc.
; :ts=8
include lmacros.h
procdef memcmp,<<dest,ptr>,<src,ptr>,<lim,word>>
push si
push di
pushds
cld
ifndef LONGPTR
mov di,ds
mov es,di
endif
ldptr si,dest
ldptr di,src
mov cx,lim
jcxz done
repe cmpsb
mov ax,0
ja greater
je done
dec ax
done:
popds
pop di
pop si
pret
greater:
inc ax
jmp done
pend memcmp
finish
end
memcpy.asm
; Copyright (C) 1984, 1985 by Manx Software Systems, Inc.
; :ts=8
include lmacros.h
procdef memcpy,<<s1,ptr>,<s2,ptr>,<lim,word>>
push si
push di
pushds
cld
ifndef LONGPTR
mov di,ds
mov es,di
endif
ldptr di,s1
ldptr si,s2
mov cx,lim
mov dx,cx
shr cx,1
jcxz chk_odd
rep movsw
chk_odd:
test dl,1
jz done
movsb
done:
retptrm s1
popds
pop di
pop si
pret
pend memcpy
finish
end
memset.asm
; Copyright (C) 1984, 1985 by Manx Software Systems, Inc.
; :ts=8
include lmacros.h
procdef memset,<<area,ptr>,<char,byte>,<lim,word>>
push di
cld
ifndef LONGPTR
mov di,ds
mov es,di
endif
ldptr di,area
mov al,char
mov ah,al
mov cx,lim
mov dx,cx
shr cx,1
jcxz nowords
rep stosw
nowords:
test dl,1
jz done
stosb
done:
retptrm area
pop di
pret
pend memset
finish
end
movblock.asm
;Copyright (C) 1983, 1985 by Manx Software Systems
; :ts=8
include lmacros.h
procdef movblock,<<src,dword>,<dest,dword>,<len,word>>
push di
push si
push ds
push es
pushf
cld
mov cx,len
les di,dest
lds si,src
cmp cx,4
jne not_int
cli
not_int:
test cx,cx
jnz not_mov_all
mov cx,8000H
jmp short movwords
not_mov_all:
mov dx,cx
shr cx,1
jz mv_skip
movwords:
rep movsw
mv_skip:
test dl,1
jz done
movsb
done:
popf
pop es
pop ds
pop si
pop di
pret
pend movblock
finish
end
movmem.asm
;Copyright (C) 1984, 1985 by Manx Software Systems
; :ts=8
include lmacros.h
procdef movmem,<<arg1,ptr>,<arg2,ptr>,<len,word>>
pushf
cld
push si
push di
pushds
ifndef LONGPTR
mov di,ds
mov es,di
endif
ldptr si,arg1
ldptr di,arg2
mov cx,len
mov ax,es
mov dx,ds
cmp ax,dx
jne move_forward
cmp di,si
je done
jb move_forward
std
add di,cx
add si,cx
dec di
dec si
test cl,1
jz nobyte
movsb
nobyte:
dec di
dec si
jmp short domove
;
move_forward:
test cl,1
jz domove
movsb
domove:
shr cx,1
jz done
rep movsw
done:
cld
popds
pop di
pop si
popf
pret
pend movmem
finish
end
olsubs.asm
; Copyright (C) 1983 1984 by Manx Software Systems
; :ts=8
codeseg segment para public 'code'
assume cs:codeseg
public $olongs
$olongs proc near
;
public $lng ;negate primary
$lng:
neg dx
neg ax
sbb dx,0
ret
;
public $lcmp ;compare primary and secondary
$lcmp:
cmp dx,bx
jne cmpdone
cmp ax,cx
je cmpdone
ja p_gt_s
sub ax,ax
dec ax
stc
ret
p_gt_s:
sub ax,ax
inc ax
cmpdone:
ret
;
public $lad ;add secondary to primary
$lad:
add ax,cx
adc dx,bx
ret
;
public $lsb ;subtract secondary from primary
$lsb:
sub ax,cx
sbb dx,bx
ret
;
public $lan ;and primary with secondary
$lan:
and ax,cx
and dx,bx
ret
;
public $lor ;or primary with secondary
$lor:
or ax,cx
or dx,bx
ret
;
public $lxr ;exclusive or primary with secondary
$lxr:
xor ax,cx
xor dx,bx
ret
;
public $lcm ;complement primary
$lcm:
not ax
not dx
ret
;
public $lls ;shift primary left by secondary
$lls:
and cl,03fH ;restrict to 63 bits
jz lsdone
lsloop:
shl ax,1
rcl dx,1
loop lsloop
lsdone:
ret
;
public $lrs ;right shift primary by secondary bits
$lrs:
and cl,03fH ;restrict to 63 bits
jz rsdone
rsloop:
sar dx,1
rcr ax,1
loop rsloop
rsdone:
ret
;
public $lur ;unsigned right shift primary by secondary bits
$lur:
and cl,03fH ;restrict to 63 bits
jz ursdone
ursloop:
shr dx,1
rcr ax,1
loop ursloop
ursdone:
ret
;
public $lml
$lml: ;long multiply (primary = primary * secondary)
push ax ;save low word
push dx ;save high word
mul bx
mov bx,ax ;keep partial product
pop ax ;get high word
mul cx
add bx,ax ;add to partial product
pop ax ;get low word
mul cx
add dx,bx ;add in partial products
ret
;
$olongs endp
codeseg ends
end
ovbgn.asm
; :ts=8
;Copyright (C) 1984 by Manx Software Systems
codeseg segment para public 'code'
dataseg segment para public 'data'
save_si dw 0
save_di dw 0
save_sp dw 0
save_bp dw 0
save_ret dw 0
extrn _Uorg_:word, _Uend_:word
dataseg ends
assume cs:codeseg,ds:dataseg
extrn ovmain_:near
public $ovbgn
$ovbgn proc near
pop save_ret
pop cx ;throw away overlay name
mov save_sp,sp
mov save_bp,bp
mov save_si,si
mov save_di,di
cld
mov di,offset _Uorg_ ;clear uninitialized data
mov cx,offset _Uend_
sub cx,di
shr cx,1
jz nobss
sub ax,ax
rep stosw
nobss:
call ovmain_
;
; fall through into ovexit code
;
public ovexit_
ovexit_:
mov bp,save_bp
mov sp,save_sp
mov si,save_si
mov di,save_di
push cx ;fake argument to replace overlay name
jmp save_ret
$ovbgn endp
codeseg ends
end $ovbgn
ovloader.c
/* Copyright (C) 1984 by Manx Software Systems */
#define OV_MAGIC 0xf2
struct ovrheader { /* overlay header header */
short o_magic;
unsigned short o_corg;
unsigned short o_csize;
unsigned short o_dorg;
unsigned short o_dsize;
unsigned short o_bss;
unsigned short o_entry;
};
static char *ovname;
#asm
public ovloader_
ovloader_ proc near
mov bx,sp
mov ax,word ptr 2[bx]
mov ovname_,ax
call _ovld_
jmp ax
ovloader_ endp
#endasm
static
_ovld()
{
int fd, flag;
register char *cp, *xp;
auto struct ovrheader hdr;
char *getenv(), path[64];
extern char *_mbot, _Cend[], _Uend[];
#ifdef DOS20
if ((cp = getenv("PATH")) == 0)
cp = "";
xp = path;
for (;;) {
strcpy(xp, ovname);
strcat(path, ".ovr");
if ((fd = open(path, 0)) != -1)
break;
do {
if (*cp == 0)
loadabort(10);
xp = path;
while (*cp) {
if (*cp == ';') {
++cp;
break;
}
*xp++ = *cp++;
}
*xp = 0;
} while (path[0] == 0);
}
#else
strcpy(path, ovname);
strcat(path, ".ovr");
if ((fd = open(path, 0)) == -1)
loadabort(10);
#endif
if (read(fd, &hdr, sizeof hdr) != sizeof hdr)
loadabort(20);
/* safety check overlay header */
if (hdr.o_magic != OV_MAGIC)
loadabort(30);
if (_mbot < hdr.o_dorg+hdr.o_dsize+hdr.o_bss)
loadabort(40);
if (_Cend > hdr.o_corg || _Uend > hdr.o_dorg)
loadabort(60);
if (_csread(fd, hdr.o_corg, hdr.o_csize) < hdr.o_csize
|| read(fd, hdr.o_dorg, hdr.o_dsize) < hdr.o_dsize)
loadabort(50);
close(fd);
return hdr.o_entry;
}
static
loadabort(code)
{
char buffer[80];
sprintf(buffer, "Error %d loading overlay: %s$", code, ovname);
bdos(9, buffer);
exit(100);
}
peek.asm
;Copyright (C) 1983, 1985 by Manx Software Systems
; :ts=8
include lmacros.h
procdef peekw,<<addr,dword>>
push ds
lds bx,addr
mov ax,ds:[bx]
pop ds
pret
pend peekw
;
entrdef peekb
procdef peek,<<addr1,dword>>
push ds
lds bx,addr1
mov al,ds:[bx]
and ax,0ffH
pop ds
pret
pend peek
;
procdef pokew,<<addr2,dword>,<val,word>>
push ds
mov ax,val
lds bx,addr2
mov ds:[bx],ax
pop ds
pret
pend pokew
;
entrdef poke
procdef pokeb,<<addr3,dword>,<val1,byte>>
push ds
mov al,val1
lds bx,addr3
mov ds:[bx],al
pop ds
pret
pend pokeb
finish
end
pointers.asm
; :ts=8
;Copyright (C) 1985 by Manx Software Systems
include lmacros.h
assume ds:dataseg
;
; ptrtoabs(lptr): convert pointer to 20-bit physical address
;
procdef ptrtoabs,<<lptr,word>,<llptr,word>>
mov ax,lptr
mov dx,llptr
mov cx,4
rol dx,cl
mov bx,dx
and bx,0fff0h
and dx,0fh
add ax,bx
adc dx,0
pret
pend ptrtoabs
;
; abstoptr(laddr): convert 20-bit physical address to pointer
;
procdef abstoptr,<<laddr,word>,<lladdr,word>>
mov ax,laddr
mov dx,lladdr
and dx,0fh
mov bx,ax
mov cx,4
ror dx,cl
shr bx,cl
and bx,0fffh
or dx,bx
and ax,0fh
pret
pend abstoptr
finish
end
port.asm
;Copyright (C) 1983, 1985 by Manx Software Systems
; :ts=8
include lmacros.h
entrdef inport
procdef inportb,<<port,word>>
mov dx,port
in al,dx
and ax,0ffH
pret
pend inportb
;
procdef inportw,<<port1,word>>
mov dx,port1
in ax,dx
pret
pend inportw
;
entrdef outport
procdef outportb,<<port2,word>,<val,byte>>
mov dx,port2
mov al,val
out dx,al
pret
pend outportb
;
procdef outportw,<<port3,word>,<val1,word>>
mov dx,port3
mov ax,val1
out dx,ax
pret
pend outportw
finish
end
ptradd.asm
; :ts=8
;Copyright (C) 1985 by Manx Software Systems
include lmacros.h
;
;char *_ptradd(lptr, long): return lptr+long
;
procdef _ptradd,<<offs,word>,<segm,word>,<incrl,word>,<incrh,word>>
mov ax,segm
sub dx,dx
mov cx,4
sloop: shl ax,1
rcl dx,1
loop sloop
add ax,offs
adc dx,0
add ax,incrl
adc dx,incrh
mov bx,ax
mov cx,4
sloop2: shr dx,1
rcr ax,1
loop sloop2
mov dx,ax
mov ax,bx
and ax,15
mov bx,dx
pret
pend _ptradd
finish
end
ptrdiff.asm
; :ts=8
;Copyright (C) 1985 by Manx Software Systems
include lmacros.h
;
; long _ptrdiff(lptr1, lptr2): return long pointer difference
;
procdef _ptrdiff,<<off1,word>,<seg1,word>,<off2,word>,<seg2,word>>
mov ax,seg1
sub ax,seg2
sbb dx,dx
mov cx,4
sloop: shl ax,1
rcl dx,1
loop sloop
add ax,off1
adc dx,0
sub ax,off2
sbb dx,0
mov bx,dx
pret
pend _ptrdiff
finish
end
rindex.asm
; :ts=8
;Copyright (C) 1983 by Manx Software Systems
include lmacros.h
procdef rindex, <<string,ptr>,<chr,byte>>
pushf
cld
push di
ifndef LONGPTR
mov di,ds
mov es,di
endif
ldptr di,string,es
mov dx,di ;save for later
sub ax,ax
mov cx,7fffH
repne scasb
mov cx,di
sub cx,dx ;compute length of string
dec di ;backup to null byte
mov al,chr ;get byte to look for
std ;now go backwards
repne scasb
je found
retnull
pop di
popf
pret
found:
retptrr di,es
inc ax
pop di
popf
pret
pend rindex
finish
end
rom.asm
; Copyright (C) 1984, 1985 by Manx Software Systems
; :ts=8
include lmacros.h
;
; If you want your stack at a fixed place, you may remove the
; "bss cstack..." statement below and change the "mov sp,cstack..."
; to load SP with the value you desire. Note that the setup of
; SS may need to be changed also. If the program is small data
; model, then SS must be equal to DS or pointers to automatic
; variables won't work.
;
; Otherwise, stacksize should be set according to your program's
; requirements.
stacksize equ 2048
;
; dataseg is the data segment address (as a paragraph #)
; this is picked from the -D option of the linker
;
;Dseg equ 040H ;physical addr 0x400, just above the int vectors
dataseg segment word public 'data'
bss cstack:byte,stacksize
public $MEMRY
$MEMRY dw -1
dw -1
public errno_
errno_ dw 0
public _dsval_,_csval_
_dsval_ dw 0
_csval_ dw 0
public _mbot_, _sbot_
_mbot_ dw 0
dw 0
_sbot_ dw 0
dw 0
;
; The variable is used with csav and cret only. Therefore if you do not
; compile the the +c option or +b option you do not need this.
;
public _lowwater_
_lowwater_ dw -1
extrn _Dorg_:byte,_Dend_:byte
extrn _Uorg_:byte,_Uend_:byte
dataseg ends
extrn _Corg_:byte,_Cend_:byte
ifdef FARPROC
extrn main_:far, $fltinit:far
else
extrn main_:near, $fltinit:near
endif
public $begin
$begin proc far
cli
cld
;
; Compute where initialzed data starts (@ next para after code)
;
mov ax,offset _Cend_+15
mov cl,4
shr ax,cl
add ax,seg _Cend_
mov ds,ax ;place where data is in rom
mov bx,dataseg ;place where data is to go in ram
mov es,bx
;
; Note: For hardware reasons the instruction which loads SS should
; be immediatly followed by the load of SP.
;
mov ss,bx
mov sp,offset cstack+stacksize
;
; copy Init data from rom to ram
mov di,0
mov cx,offset _Dend_
inc cx
shr cx,1
jcxz nocopy
mov si,0
rep movsw
nocopy:
;
; clear uninitialized data
mov di,offset _Uorg_
mov cx,offset _Uend_
sub cx,di
inc cx
shr cx,1
jcxz noclear
sub ax,ax
rep stosw
noclear:
;
assume ds:dataseg,es:dataseg
mov ds,bx ;set DS, now DS, SS, ES are equal
mov di,$MEMRY
inc di
and di,0fffeH ;adjust to word boundary
mov $MEMRY,di ;save memory allocation info for sbrk()
mov $MEMRY+2,ds
mov _mbot_,di
mov _mbot_+2,ds
mov _sbot_,0ffffH ;this is the heap limit for sbrk()
mov _sbot_+2,0fff0h
mov _dsval_,ds
mov _csval_,cs ;this is of dubious value in large code
sti
call $fltinit ;setup floating point software/hardware
jnc flt_ok
hlt ;program needs 8087 and one wasn't found
flt_ok:
jmp main_ ;main shouldn't return in ROM based system
$begin endp
codeseg ends
end $begin
segread.asm
; :ts=8
;Copyright (C) 1983, 1985 by Manx Software Systems
include lmacros.h
procdef segread,<<segs,ptr>>
ifdef LONGPTR
mov cx,es
ldptr bx,segs,es
ifdef FARPROC
mov ax,4[bp]
mov es:[bx],ax
else
mov es:[bx],cs
endif
mov es:2[bx],ss
mov es:4[bx],ds
mov es:6[bx],cx
else
mov bx,segs
ifdef FARPROC
mov ax,4[bp]
mov [bx],ax
else
mov [bx],cs
endif
mov 2[bx],ss
mov 4[bx],ds
mov 6[bx],es
endif
pret
pend segread
finish
end
setjmp.asm
; :ts=8
;Copyright (C) 1983 by Manx Software Systems
include lmacros.h
procdef setjmp,<<jmpbuf,ptr>>
pushds
ldptr bx,jmpbuf,ds
lea ax,jmpbuf
mov [bx],ax
mov ax,0[bp] ;get caller's BP
mov 2[bx],ax
mov 4[bx],si
mov 6[bx],di
mov ax,2[bp] ;caller's IP
mov 8[bx],ax
ifdef FARPROC
mov ax,4[bp] ;caller's CS
mov 10[bx],ax
endif
sub ax,ax
popds
pret
pend setjmp
;
procdef longjmp,<<jbuf,ptr>,<retval,word>>
mov ax,retval
ifndef LONGPTR
mov bx,ds
mov es,bx
endif
ldptr bx,jbuf,es
mov sp,es:[bx]
mov bp,es:2[bx]
mov si,es:4[bx]
mov di,es:6[bx]
test ax,ax
jnz ax_ok
inc ax
ax_ok:
ifdef FARPROC
jmp es:dword ptr 8[bx]
else
jmp es:word ptr 8[bx]
endif
pend longjmp
finish
end
setmem.asm
; :ts=8
;Copyright (C) 1983 by Manx Software Systems
include lmacros.h
procdef setmem,<<src,ptr>,<len,word>,<val,byte>>
pushf
cld
push di
ifndef LONGPTR
mov di,ds
mov es,di
endif
ldptr di,src,es
mov cx,len
mov al,val
mov ah,al
mov dx,cx
shr cx,1
jz skip
rep stosw
skip:
test dl,1
jz done
stosb
done:
pop di
popf
pret
pend setmem
finish
end
strcat.asm
; :ts=8
;Copyright (C) 1983, 1985 by Manx Software Systems
include lmacros.h
procdef strcat,<<a,ptr>,<b,ptr>>
mov dx,7fffH
jmp short catcommon
pend strcat
procdef strncat,<<str1,ptr>,<str2,ptr>,<len,word>>
mov dx,len
catcommon:
cld
push si
push di
pushds
ifndef LONGPTR
mov di,ds
mov es,di
endif
ldptr di,str1
sub ax,ax
mov cx,7fffH
repne scasb ;find end of destination string
dec di ;backup to null byte
ldptr si,str2
mov cx,dx
cpyloop:
lodsb
stosb
test al,al
loopnz cpyloop
jz nul_ok
sub al,al ;guarantee that string is nul terminated
stosb
nul_ok:
popds
pop di
pop si
retptrm str1
pret
pend strncat
finish
end
strchr.asm
; :ts=8
;Copyright (C) 1985 by Manx Software Systems
include lmacros.h
procdef strchr, <<arg,ptr>,<val,byte>>
cld
push si
pushds
ldptr si,arg,ds
mov bl,val
lookloop:
lodsb
cmp al,bl
je found
test al,al
jnz lookloop
retnull
popds
pop si
pret
found:
retptrr si,ds
dec ax
popds
pop si
pret
pend strchr
finish
end
strcmp.asm
; :ts=8
;Copyright (C) 1983 by Manx Software Systems
include lmacros.h
procdef strcmp,<<s1,ptr>,<s2,ptr>>
cld
push si
push di
pushds
ldptr si,s1
ifndef LONGPTR
mov di,ds
mov es,di
endif
ldptr di,s2
cmploop:
lodsw
scasw
jne word_notequal
test al,al
jz equal
test ah,ah
jnz cmploop
jmp short equal
pend strcmp
procdef strncmp,<<str1,ptr>,<str2,ptr>,<len,word>>
mov cx,len
mov dx,cx
shr cx,1 ;# of times through word loop
cld
push si
push di
pushds
ldptr si,str1
ifndef LONGPTR
mov di,ds
mov es,di
endif
ldptr di,str2
jcxz words_equal
ncmploop:
lodsw
scasw
jne word_notequal
test al,al
jz equal
test ah,ah
loopnz ncmploop
jz equal
words_equal:
test dl,1
jz equal
cmpsb
jne notequal
equal:
sub ax,ax
done:
popds
pop di
pop si
pret
word_notequal:
sub di,2 ;back up to first byte in word
scasb ;and redo the compare a byte at a time
jne notequal
test al,al ;if end of string, this was a false mismatch
jz equal
mov al,ah ;get second byte
scasb ;this must be not equal, since the words aren't equal
notequal:
sbb ax,ax
js done ;if -1 then s1<s2 and we are done
inc ax ;else, ==0 and s1>s2
jmp done
pend strncmp
finish
end
strcpy.asm
; :ts=8
;Copyright (C) 1983, 1985 by Manx Software Systems
include lmacros.h
procdef strcpy,<<str1,ptr>,<str2,ptr>>
cld
push si
push di
pushds
ifndef LONGPTR
mov di,ds
mov es,di
endif
ldptr di,str2
mov cx,0ffffH
mov al,0
repne scasb
not cx ;real length of string
ldptr di,str1
ldptr si,str2
shr cx,1
jcxz nowords
rep movsw
nowords:
jnc nobyte
movsb
nobyte:
popds
pop di
pop si
retptrm str1
pret
pend strcpy
finish
end
stricmp.asm
; :ts=8
;Copyright (C) 1988 by Manx Software Systems
include lmacros.h
procdef stricmp,<<s1,ptr>,<s2,ptr>>
push si
push di
pushds
sub ah,ah
sub bh,bh
ldptr si,s1
ldptr di,s2
cmploop:
lodsb
; convert al to lower case if needed
cmp al,'A'
jl skip
cmp al,'Z'
jg skip
add al,'a'-'A'
skip:
ifdef LONGPTR
mov bl,byte ptr es:[di]
else
mov bl,byte ptr [di]
endif
inc di
; convert bl to lower case if needed
cmp bl,'A'
jl skip2
cmp bl,'Z'
jg skip2
add bl,'a'-'A'
skip2:
; Now "compare bytes"
cmp al,bl
jne word_notequal
test al,al
jnz cmploop
equal:
popds
pop di
pop si
pret
word_notequal:
sub al,bl
popds
pop di
pop si
pret
pend stricmp
finish
end
strlen.asm
; :ts=8
;Copyright (C) 1983 by Manx Software Systems
include lmacros.h
procdef strlen,<<str1,ptr>>
cld
push di
ifndef LONGPTR
mov di,ds
mov es,di
endif
ldptr di,str1
mov bx,di ;save for later
sub ax,ax
mov cx,7fffH
repne scasb
mov ax,di
sub ax,bx ;compute length of string
dec ax
pop di
pret
pend strlen
finish
end
strlwr.c
#include <ctype.h>
strlwr(string)
unsigned char *string;
{
register unsigned char *place;
place = string;
while ( *place ) {
*place = tolower(*place);
place ++;
}
return string;
}
strncpy.asm
; :ts=8
;Copyright (C) 1983, 1985 by Manx Software Systems
include lmacros.h
procdef strncpy,<<str1,ptr>,<str2,ptr>,<len,word>>
cld
push si
push di
pushds
mov cx,len
ifndef LONGPTR
mov di,ds
mov es,di
endif
ldptr di,str1
ldptr si,str2
jcxz cpydone
cpyloop:
lodsb
test al,al
jz zerofill
stosb
loop cpyloop
jmp short cpydone
zerofill:
rep stosb
cpydone:
popds
pop di
pop si
retptrm str1
pret
pend strncpy
finish
end
strrchr.asm
; :ts=8
;Copyright (C) 1983 by Manx Software Systems
include lmacros.h
procdef strrchr, <<string,ptr>,<chr,byte>>
pushf
cld
push di
ifndef LONGPTR
mov di,ds
mov es,di
endif
ldptr di,string,es
mov dx,di ;save for later
sub ax,ax
mov cx,7fffH
repne scasb
mov cx,di
sub cx,dx ;compute length of string
dec di ;backup to null byte
mov al,chr ;get byte to look for
std ;now go backwards
repne scasb
je found
retnull
pop di
popf
pret
found:
retptrr di,es
inc ax
pop di
popf
pret
pend strrchr
finish
end
strrev.asm
; :ts=8
;Copyright (C) 1988 by Manx Software Systems
include lmacros.h
ifdef FARPROC
extrn strlen_:far
else
extrn strlen_:near
endif
procdef strrev,<<string,ptr>>
push si
pushds
ifdef LONGPTR
mov ax,word ptr string+2
push ax
endif
mov si,word ptr string
push si
call strlen_
ifdef LONGPTR
add sp,4
mov ds,word ptr string+2
else
pop cx
endif
add ax,si
dec ax
mov bx,ax
; si should point to start of string
; bx should point to rear of string
jmp loop_test
again:
; swap word ptr by [si] and word ptr by [di]
mov dl,byte ptr [si]
mov cl,byte ptr [bx]
mov byte ptr [si],cl
mov byte ptr [bx],dl
inc si
dec bx
loop_test:
cmp si,bx
jb again
mov ax,word ptr string
ifdef LONGPTR
mov dx,word ptr string+2
endif
popds
pop si
pret
pend strrev
codeseg ends
end
strstr.asm
; :ts=8
;Copyright (C) 1988 by Manx Software Systems
include lmacros.h
ifndef FARPROC
extrn strncmp_:near
extrn strlen_:near
else
extrn strncmp_:far
extrn strlen_:far
endif
procdef strstr,<<s1,ptr>,<s2,ptr>>
push si
push di
pushds
ldptr si,s2,es
ifdef LONGPTR
mov di,es
push es
endif
push si
call strlen_
ifdef LONGPTR
add sp,4
mov es,di
else
pop cx
endif
mov di,ax
ldptr bx,s1,ds
; bx pointer to first string ( offset only )
; si pointer to second string ( offset only )
; di length of second string ( offset only )
jmp test_condition
top_of_loop:
; save bx
push bx
push di
ifdef LONGPTR
push ds
endif
push bx
ifdef LONGPTR
push es
endif
push si
call strncmp_
ifdef LONGPTR
add sp,10
mov es,word ptr s2+2
else
add sp,6
endif
; restore bx
pop bx
test ax,ax
jz return_succ
inc bx
test_condition:
cmp byte ptr [bx],0
jne top_of_loop
exit_failure:
ifdef LONGPTR
xor dx,dx
endif
xor ax,ax
jmp final_exit
return_succ:
mov ax,bx
ifdef LONGPTR
mov dx,word ptr s1+2
endif
final_exit:
popds
pop di
pop si
pret
pend strstr
finish
end
swapmem.asm
; :ts=8
;Copyright (C) 1984 by Manx Software Systems
include lmacros.h
procdef swapmem,<<str1,ptr>,<str2,ptr>,<len,word>>
push si
push di
pushds
ifndef LONGPTR
mov di,ds
mov es,di
endif
ldptr si,str1
ldptr di,str2
mov cx,len
jcxz done
ifdef LONGPTR
mov ax,ds
mov dx,es
cmp ax,dx
jne swaploop
endif
cmp di,si
je done
swaploop:
mov al,es:[di]
xchg al,ds:[si]
stosb
inc si
loop swaploop
done:
popds
pop di
pop si
pret
pend swapmem
finish
end
sysint.asm
; :ts=8
;Copyright (C) 1983 by Manx Software Systems
include lmacros.h
procdef sysint,<<num,byte>,<sregs,ptr>,<dregs,ptr>>
sub sp,14
push si
push di
push es
push ds
;
; build instruction sequence on the stack to issue int
; and restore ss:sp to value before int.
; Note: All this is because some handlers don't restore ss and sp.
;
mov byte ptr -10[bp],0cdH ;int xx
mov al,num
mov byte ptr -9[bp],al
mov word ptr -8[bp],0cd8cH ;mov bp,cs
mov word ptr -6[bp],0d58eH ;mov ss,bp
mov byte ptr -4[bp],0bcH ;mov sp,xx
mov ax,sp
sub ax,6
mov word ptr -3[bp],ax
mov byte ptr -1[bp],0cbH ;retf
mov word ptr -12[bp],ss ;set up pointer to above code
lea ax,-10[bp]
mov word ptr -14[bp],ax
;
ldptr bx,sregs,ds
mov ax,[bx]
push 2[bx] ;value to go into BX
mov cx,4[bx]
mov dx,6[bx]
mov si,8[bx]
mov di,10[bx]
mov es,14[bx]
mov ds,12[bx]
pop bx
push bp
call ss:dword ptr -14[bp]
pop bp
push ds ;save values so we have working registers
push bx
ldptr bx,dregs,ds
ifdef LONGPTR
mov [bx],ax
pop 2[bx] ;value returned in BX
mov 4[bx],cx
mov 6[bx],dx
mov 8[bx],si
mov 10[bx],di
pop 12[bx] ;value returned in DS
mov 14[bx],es
pop ds
else
mov ss:14[bx],es
pop ss:2[bx] ;value returned in BX
pop ss:12[bx] ;value returned in DS
pop ds
mov [bx],ax
mov 4[bx],cx
mov 6[bx],dx
mov 8[bx],si
mov 10[bx],di
endif
pop es
pop di
pop si
pushf
pop ax
add sp,14
pret
pend sysint
finish
end
toupper.asm
; Copyright (C) 1983 by Manx Software Systems
include lmacros.h
procdef toupper,<<val1,byte>>
;
mov al,val1
sub ah,ah
cmp al,'a'
jl tu_done
cmp al,'z'
jg tu_done
sub al,'a'-'A'
tu_done:
pret
pend toupper
;
;
procdef tolower,<<val2,byte>>
;
mov al,val2
sub ah,ah
cmp al,'A'
jl skip
cmp al,'Z'
jg skip
add al,'a'-'A'
skip:
pret
pend tolower
finish
end