Category : C Source Code
Archive   : SMALLC.ZIP
Filename : CPCLIB.ASM
Output of file : CPCLIB.ASM contained in archive : SMALLC.ZIP
;TITLE (C) Copyright CAPROCK SYSTEMS, INC. 1982
;SUBTTL small-c:PC PC-DOS RUN TIME LIBRARY
;
;
DATASEG SEGMENT BYTE PUBLIC 'code'
DB '(C) Copyright CAPROCK SYSTEMS, INC. 1982'
;
;
;
;FOR I/O BUFFERS
FCBSIZE EQU 40 ;PCDOS FCB SIZE + 3
BUFFER EQU 4 ;SPACE NEEDED FOR NEXT PTR AND UNUSED CNT
BUFSIZ EQU 512 ;DISK BLOCK SIZE
NEXTP EQU 0 ;OFFSET IN BUFFER OF NEXT CHAR PTR
UNUSED EQU 2 ;OFFSET IN BUFFER OF REMAINING CHARS
FLAG EQU 37 ;OFFSET IN FCB OF FLAG TYPING AN FCB
NBUFS EQU 4 ;NUMBER OF IOBUFS (SEE BELOW)
FREEFLG EQU 128 ;FCB NOT ALLOCATED
EOFFLG EQU 2 ;EOF ENCOUNTERED ON FILE
WRTFLG EQU 1 ;FILE OPENED FOR WRITING
CTRLZ EQU 26
EOL EQU 13 ;END OF LINE CHARACTER
LF EQU 10 ;LINE FEED
;
;PCDOS INT 21H FUNCTION CODES
;
GETCH EQU 1
PUTCH EQU 2
GETSTR EQU 10
SELECT EQU 14
DMA EQU 26
OPEN EQU 15
DELETE EQU 19
CREATE EQU 22
CLOSE EQU 16
SEQREAD EQU 20
SEQWRITE EQU 21
GETDFLT EQU 25 ;GET CURRENT LOGGED DRIVE
PARSE EQU 41
;
;
; FCB STORAGE AND I/O BUFFERS
;
DFLTDSK DB 0 ;BYTE FOR DEFAULT DISK
IOBUFS DB FCBSIZE-3 DUP(?)
DB FREEFLG,0,0
DB BUFFER+BUFSIZ DUP(?)
;
DB FCBSIZE-3 DUP(?)
DB FREEFLG,0,0
DB BUFFER+BUFSIZ DUP(?)
;
DB FCBSIZE-3 DUP(?)
DB FREEFLG,0,0
DB BUFFER+BUFSIZ DUP(?)
;
DB FCBSIZE-3 DUP(?)
DB FREEFLG,0,0
DB BUFFER+BUFSIZ DUP(?)
DATASEG ENDS
;
;
;
CSEG SEGMENT BYTE PUBLIC 'code'
ASSUME CS:CSEG,DS:DATASEG
;-------------------------------------------------
;
; Small-C:PC Run Time Library for IBM PC-DOS
;
; V1 As of June, 1982
;
;--------------------------------------------------
db '(C) Copyright CAPROCK SYSTEMS, INC. 1982'
;
;
; Fetch byte at offset BX in Stack Segment (SS) and sign extend into BX
;
PUBLIC CCGCHAR
CCGCHAR:
MOV BP,BX
MOV AL,[BP]
CBW
MOV BX,AX
RET
;
; Fetch a 16-bit integer at offset BX in SS into BX
;
PUBLIC CCGINT
CCGINT:
MOV BP,BX
MOV BX,[BP]
RET
;
; Store BL into SS at offset in DX
;
PUBLIC CCPCHAR
CCPCHAR:
MOV BP,DX
MOV [BP],BL
RET
;
; Store BX into SS at Offset in DX
;
PUBLIC CCPINT
CCPINT:
MOV BP,DX
MOV [BP],BX
RET
;
; Multiply DX by BX and return result in BX
;
PUBLIC CCMULT
CCMULT:
MOV AX,DX
IMUL BX
MOV BX,AX
RET
;
; Divide DX by BX, return quotient in BX, remainder in DX
;
PUBLIC CCDIV
CCDIV:
MOV AX,DX
MOV CX,1
IMUL CX
IDIV BX
MOV BX,AX
RET
;
; Unsigned compare of DX to BX, carry set if DX < BX
;
PUBLIC CCUCMP
CCUCMP:
CMP DH,BH
JNZ CC@1
CMP DL,BL
CC@1:
MOV BX,1
RET
;
; Test if DX >= BX (Unsigned)
;
PUBLIC CCUGE
CCUGE:
CALL CCUCMP
JNC CC@2
DEC BX
CC@2:
RET
;
; Test if DX < BX (Unsigned)
;
PUBLIC CCULT
CCULT:
CALL CCUCMP
JC CC@3
DEC BX
CC@3:
RET
;
; Test if DX > BX (Unsigned)
;
PUBLIC CCUGT
CCUGT:
XCHG BX,DX
CALL CCULT
RET
;
; Test if DX <= BX (Unsigned)
;
PUBLIC CCULE
CCULE:
XCHG BX,DX
CALL CCUGE
RET
;
; Signed Compare of DX and BX
;
; carry set if DX < BX, zero/non-zero set for equality
;
PUBLIC CCCMP
CCCMP:
SUB DL,BL
SBB DH,BH
MOV BX,1
JS CCCMP1
OR DH,DL
RET
CCCMP1:
OR DH,DL
STC
RET
;
; Test if DX = BX and set BX=1 if true, else 0
;
PUBLIC CCEQ
CCEQ:
CALL CCCMP
JZ CC@4
DEC BX
CC@4:
RET
;
;
; Test if DX != BX
;
PUBLIC CCNE
CCNE:
CALL CCCMP
JNZ CC@5
DEC BX
CC@5:
RET
;
; Test if DX < BX
;
PUBLIC CCLT
CCLT:
CALL CCCMP
JC CC@6
DEC BX
CC@6:
RET
;
; Test if DX > BX
;
PUBLIC CCGT
CCGT:
XCHG BX,DX
CALL CCLT
RET
;
; Test if DX <= BX
;
PUBLIC CCLE
CCLE:
CALL CCCMP
JC CC@7
JZ CC@7
DEC BX
CC@7:
RET
;
; Test if DX >= BX
;
PUBLIC CCGE
CCGE:
XCHG BX,DX
CALL CCLE
RET
;
;-------------------------------------------------
;
; PC-DOS I/O MODULES
; (C) CAPROCK SYSTEMS, INC.
; P.O. BOX 13814
; ARLINGTON, TEXAS 76013
;
;-------------------------------------------------
;
;
;
; pcdos(ah,dx)
;
PUBLIC QZPCDOS
QZPCDOS:
POP CX
POP DX
POP AX
PUSH AX
PUSH DX
PUSH CX
MOV AH,AL
INT 21H
CBW
MOV BX,AX
RET
;
;
; out808X(port,AL)
;
;
PUBLIC QZOUT808X
QZOUT808X:
POP CX
POP AX
POP DX
PUSH DX
PUSH AX
OUT DX,AL
JMP CX
;
;
; int var = in808X(port)
;
;
PUBLIC QZIN808X
QZIN808X:
POP CX
POP DX
PUSH DX
IN AL,DX
CBW
MOV BX,AX
JMP CX
;
;
; VIDEO I/O THRU ROM BIOS
;
; int10(AH,AL,BH,BL,CH,CL,DH,DL);
;
;
PUBLIC QZINT10
QZINT10:
POP SI
POP DX
POP AX
MOV DH,AL
POP CX
POP AX
MOV CH,AL
POP BX
POP AX
MOV BH,AL
MOV DI,BX
POP AX
POP BX
MOV AH,BL
MOV BX,DI
PUSH AX
PUSH AX
PUSH BX
PUSH BX
PUSH CX
PUSH CX
PUSH DX
PUSH DX
PUSH SI
INT 10H
RET
;
;
; ASYNC I/O THRU ROM BIOS
;
; BX = INT14(AH,AL,DX)
;
PUBLIC QZINT14
QZINT14:
POP CX
POP DX
POP BX
POP AX
PUSH AX
PUSH BX
PUSH DX
MOV AH,AL
MOV AL,BL
INT 14H
MOV BX,AX
JMP CX
;
;
; copy program prefix to stack area
;
; copyprefix(ptr);
;
PUBLIC QZCOPYPREF
QZCOPYPREF:
POP CX
POP DI ;OFFSET INTO STACK OF DESTINATION
PUSH DI
PUSH CX
MOV AX,SS
PUSH ES
MOV ES,AX ;PREPARE FOR MOVE
MOV SI,0
CLD
MOV CX,128 ;NUMBER WORDS TO MOVE
REP MOVSW
POP ES
RET
;
;
; SOUND BELL
;
; bell()
;
PUBLIC QZBELL
QZBELL:
MOV AX,7 ;BELL CHARACTER
PUSH AX
CALL QZPUTCHAR ;SOUND IT
POP AX
RET
;
;
; CLEAR SCREEN
;
; clrscreen();
;
PUBLIC QZCLRSCREE
QZCLRSCREE:
INT 11H ;EQUIPMENT
MOV SI,AX
AND SI,30H
MOV AX,0B800H ;COLOR CARD RAM
MOV CX,8192 ;WORD COUNT
CMP SI,30H
JNE CC@8
MOV AX,0B000H ;BW CARD RAM
MOV CX,2048 ;WORD COUNT
CC@8:
MOV ES,AX
MOV AH,15 ;VIDEO STATE
INT 10H
CMP AL,4 ;GRAPHICS MODE?
JC CC@9
CMP SI,30H ;BW CARD?
JE CC@9
XOR AX,AX ;FILL WORD
JMP SHORT CC@10
CC@9:
MOV AX,' '+7*256 ;FILL WORD
CC@10:
XOR DI,DI
CLD
REP STOSW ;CLEAR VIDEO MEMORY
MOV AH,2 ;MOVE CURSOR
XOR DX,DX ;0,0 (HOME)
XOR BH,BH ;ACTIVE PAGE
INT 10H
RET
;
;
;
; gets(buff)
;
;
PUBLIC QZGETS
QZGETS:
POP BX
POP DX
PUSH DX
PUSH BX
SUB DX,2
MOV BP,DX
MOV CX,[BP]
MOV AX,004FH ;ASSUMED LENGTH = 80 CHARS - 1 FOR EOL
MOV [BP],AX ;SET UP BUFFER THE WAY PC-DOS WANTS IT
PUSH DS
MOV AX,SS
MOV DS,AX
MOV AH,GETSTR
INT 21H
POP DS
MOV AX,[BP] ;LENGTH IN AH
MOV [BP],CX ;RESTORE SAVED BYTES
ADD BP,2
MOV BX,BP
MOV AL,AH
CBW
ADD BP,AX
XOR AL,AL
MOV [BP],AL ;INSERT C:PC STRING TERMINATOR
CALL PUTLF
RET
;
PUTLF:
MOV AH,PUTCH
MOV DL,LF
INT 21H
RET
;
;
; getchar()
;
;
PUBLIC QZGETCHAR
QZGETCHAR:
MOV AH,GETCH
INT 21H
MOV BL,AL
XOR BH,BH
CMP AL,CTRLZ
JNZ GETC1
MOV BX,-1
GETC1:
CMP AL,EOL
JNZ GC2
CALL PUTLF
GC2:
RET
;
;
; putchar(c)
;
;
PUBLIC QZPUTCHAR
QZPUTCHAR:
POP BX
POP DX
PUSH DX
PUSH BX
MOV AH,PUTCH
INT 21H
MOV BL,DL
CMP DL,EOL
JNZ PUTC1
CALL PUTLF
PUTC1:
XOR BH,BH
RET
;
;
; puts(cp)
;
;
PUBLIC QZPUTS
QZPUTS:
POP CX
POP BP
PUSH BP
PUSH CX
MOV AH,PUTCH
PS1:
MOV DL,[BP]
OR DL,DL
JNZ PS2
RET
PS2:
INC BP
INT 21H
JMP PS1
;
;
; Run Time Initialize
;
;
CCGO:
MOV CL,4 ;SHIFT COUNT
MOV AX,STACK
MOV SS,AX
MOV BX,DS
SUB AX,BX
SAL AX,CL ;MAKE DIFF 16 BITS
NEG AX
ADD AX,DS:6
MOV SP,AX ;MAX STACK POINTER
PUSH DS ;SAVE PREFIX ADDR
SUB AX,AX
PUSH AX ;LONG EXIT ADDRESS IS NOW ON TOP
MOV AX,DATASEG
PUSH DS
MOV DS,AX
MOV AH,GETDFLT
INT 21H
INC AL
MOV BX,OFFSET DFLTDSK
MOV [BX],AL
POP DS
EXTRN QZMAIN:NEAR
CALL QZMAIN ;EXECUTE USER'S small-c:PC PROGRAM
; FALL THRU TO EXIT CODE
;
;
; exit()
;
PUBLIC QZEXIT
QZEXIT:
MOV CL,4
MOV AX,SS
MOV BX,DS
SUB AX,BX
SAL AX,CL
NEG AX
ADD AX,DS:6
SUB AX,4
MOV SP,AX ;PRUNE STACK
MOV AX,DATASEG
PUSH DS
MOV DS,AX
MOV BX,OFFSET DFLTDSK
MOV DL,[BX]
DEC DL
MOV AH,SELECT
INT 21H
POP DS
DB 0CBH ;LONG RETURN TO DOS
;
;
; fopen(name,mode)
;
PUBLIC QZFOPEN
QZFOPEN:
POP AX
POP CX ;MODE
POP SI ;PREPARE FOR PARSE
PUSH SI
PUSH CX
PUSH AX
PUSH CX ;SAVE MODE
CALL GRABIO ;GET FCB
POP CX ;RESTORE MODE FOR LATER USE
OR BX,BX ;ANY LUCK IN GETTING AN FCB?
JNZ FO1
RET ;NOPE
FO1:
MOV DX,BX ;SAVE OFFSET
PUSH DS ;SAVE CALLER'S DS
MOV AX,DATASEG
MOV DS,AX ;ADDRESS OUR DATA SEGMENT
ADD BX,FCBSIZE ;OFFSET OF BUFFER
MOV AX,BX
ADD AX,BUFFER ;IO AREA OFFSET
MOV [BX]+NEXTP,AX ;NEXT AVAILABLE CHAR
PUSH DS
MOV AX,DS
MOV ES,AX
MOV DI,DX ;ES:DI -> FCB
MOV AX,SS
MOV DS,AX ;DS:SI -> NAME
MOV AH,PARSE
XOR AL,AL ;PARSE WITHOUT SKIPPING ANYTHING
INT 21H
POP DS ;RESTORE OUR DS
OR AL,AL ;ANY LUCK?
JNZ FORET ;JUMP IF NOT
MOV AL,[DI]+1 ;SEE IF WE HAD A VALID FILENAME
CMP AL,20H ;BLANK?
JNZ FO2 ;NOPE, SO IT MUST BE SOMETHING THERE
FORET:
POP DS ;RESTORE CALLER'S DS
XOR BX,BX ;SET RETURN STATUS
RET ;LEAVE
FO2:
MOV BX,DX ;RESTORE OFFSET OF FCB
MOV AL,[BX] ;DRIVE
PUSH DX ;SAVE ACCROSS CALL
PUSH CX
PUSH AX
CALL PCDOSDSK ;SELECT IT
POP AX
POP BP ;MODE OFFSET INTO BP FOR STACK ACCESS
POP DX
MOV AL,[BP] ;GET MODE CHAR
CMP AL,72H ;MODE='r'
JZ FO3
CMP AL,52H ;MODE='R'
JNZ FO5
FO3:
MOV AH,OPEN
INT 21H ;OPEN THE FILE
OR AL,AL
JZ FO4 ;NO ERROR JUMP
FO3@1:
PUSH DX ;FCB OFFSET
CALL FREEIO ;GIVE IT UP
POP DX
JMP FORET
FO4:
XOR AX,AX
FO4@1:
MOV [BX]+FCBSIZE+UNUSED,AX ;SET UNUSED BUFFER BYTES
XOR AX,AX
MOV [BX]+32,AL ;INIT SOME FCB FIELDS
MOV [BX]+33,AX
MOV [BX]+35,AX
MOV AX,BUFSIZ
MOV [BX]+14,AX
POP DS ;RESTORE CALLER'S DS
RET ;LEAVE WITH BX SET TO FCB OFFSET
FO5:
CMP AL,77H ;MODE='w'
JZ FO6
CMP AL,57H ;MODE='W'
JNZ FO3@1 ;TAKE ERROR EXIT
FO6:
MOV AH,DELETE
INT 21H ;DELETE FILE IF IT CURRENTLY EXISTS
MOV AH,CREATE
INT 21H ;CREATE IT
OR AL,AL ;OK?
JNZ FO3@1 ;TAKE ERROR EXIT IF NOT
MOV BX,DX
MOV AL,WRTFLG
MOV [BX]+FLAG,AL ;INDICATE HOW FILE IS OPENED
MOV AX,BUFSIZ ;NUMBER OF UNUSED BUFFER POSITIONS
JMP FO4@1
;
;
;
; grabio()
;
;
GRABIO:
PUSH DS
MOV AX,DATASEG
MOV DS,AX
MOV BX,OFFSET IOBUFS+FLAG
MOV CX,NBUFS
MOV AL,FREEFLG
GI1:
CMP AL,[BX]
JZ GI2
ADD BX,FCBSIZE+BUFFER+BUFSIZ
LOOP GI1
XOR BX,BX
JMP GI3
GI2:
XOR AL,AL
MOV [BX],AL
SUB BX,FLAG
GI3:
POP DS
RET
;
;
;
; freeio(unit)
;
;
FREEIO:
POP CX
POP BX
PUSH BX
MOV AL,FREEFLG
MOV [BX]+FLAG,AL
XOR BX,BX
JMP CX
;
;
;
; pcdosdsk(drive)
;
;
PCDOSDSK:
POP CX
POP DX
PUSH DX
OR DL,DL
JNZ PD1
; SELECT DEFAULT DRIVE
PUSH BX
MOV BX,OFFSET DFLTDSK
MOV DL,[BX]
POP BX
PD1:
DEC DL
MOV AH,SELECT
INT 21H
JMP CX
;
;
;
; fclose(unit)
;
;
PUBLIC QZFCLOSE
QZFCLOSE:
POP CX
POP BX ;FCB OFFSET
PUSH BX
PUSH CX
MOV SI,1 ;DEFAULT RETURN CODE
PUSH DS ;SAVE CALLER'S DS
MOV AX,DATASEG
MOV DS,AX
MOV AL,WRTFLG
AND AL,[BX]+FLAG ;OPENED FOR WRITE?
JZ FC3 ;JUMP IF NOT
MOV AX,CTRLZ
PUSH AX ;CHAR TO WRITE
PUSH BX ;UNIT TO GO TO
CALL QZPUTC ;CTRLZ AT FILE END
POP BX
POP AX
; FILL BUFFER WITH FILL CHAR
MOV DX,BX
MOV AX,[BX]+FCBSIZE+NEXTP ;OFFSET OF NEXT AVAILABLE CHAR
MOV CX,DX
ADD CX,FCBSIZE+BUFFER+BUFSIZ ;OFFSET PAST LAST IOAREA BYTE
SUB CX,AX ;NUMBER OF CHARS TO FILL
PUSH CX ;SAVE UNUSED BYTE COUNT
JLE FC0 ;JUMP IF NONE
MOV DI,AX ;START ADDRESS ES:DI
MOV AX,DS
MOV ES,AX
MOV AL,0 ;FILL CHAR
CLD ;LEFT TO RIGHT
REP STOSB ;FILL BUFFER
FC0:
MOV AX,SEQWRITE
PUSH AX
PUSH DX ;FUNCTION AND UNIT NOW ON STACK
CALL PCDOSIO ;WRITE SECTOR
MOV AX,BX ;SAVE RETURN CODE
POP BX ;RESTORE UNIT
POP CX
OR AX,AX
JNS FC1
MOV SI,0
FC1:
POP CX ;RESTORE UNUSED COUNT
NEG CX ;PREPARE TO REDUCE DOS COUNT
JNS FC3 ;NO SIGN IMPLIES DOS COUNT IS OK
MOV AX,1 ;PREPARE FOR OVERFLOW
ADD [BX]+16,CX ;NEW LOW PART
JNO FC3 ;NO OVERFLOW => NO HIGH PART CHANGE
ADD [BX]+18,AX ;NEW HIGH PART
FC3:
MOV DX,BX
MOV AH,CLOSE
INT 21H ;CLOSE FILE
OR AL,AL
JNS FC2
MOV SI,0
FC2:
PUSH BX
CALL FREEIO
POP BX
POP DS
MOV BX,SI
RET
;
;
;
; pcdosio(fn,unit)
;
;
PCDOSIO:
POP CX
POP DX ;UNIT= OFFSET IN DS OF FCB
POP BX ;FUNCTION WANTED
PUSH BX
PUSH DX
PUSH CX
PUSH DS ;SAVE CALLER'S DS
MOV AX,DATASEG
MOV DS,AX
XOR AH,AH
XCHG BX,DX
MOV AL,[BX] ;DRIVE NUMBER
XCHG BX,DX
PUSH DX
PUSH AX
CALL PCDOSDSK ;SELECT IT
POP AX
POP DX
MOV CX,DX ;SAVE UNIT
ADD DX,FCBSIZE+BUFFER ;IO AREA OFFSET
MOV AH,DMA
INT 21H ;SET TRANSFER ADDRESS
MOV DX,CX ;DS:DX = FCB ADDRESS
MOV AH,BL ;FUNCTION CODE
INT 21H
MOV CL,AL ;STATUS
MOV AH,DMA
POP DS ;RESET DS TO PREFIX
MOV DX,80H
INT 21H ;DMA BACK TO DEFAULT
MOV AL,BL ;SAVE FUNCTION
XOR BX,BX
OR CL,CL
JZ PDI1
CMP AL,SEQREAD ;DID USER READ?
JNZ PDI0 ;CONSIDER IT AN ERROR
CMP CL,03H ;PARTIALLY FULL BUFFER?
JZ PDI1 ;THAT'S OK
PDI0:
NOT BX
PDI1:
RET
;
;
;
; getc (unit)
;
;
PUBLIC QZGETC
QZGETC:
POP CX
POP BX ;UNIT
PUSH BX
PUSH CX
PUSH BX
CALL CGET ;GET NEXT CHARACTER
POP DX ;UNIT
CMP BL,EOL ;END OF LINE
JNZ GC1 ;GO ON BACK IF NOT
PUSH BX ;SAVE EOL ON STACK
PUSH DX ;UNIT
CALL CGET ;ABSORB LF
POP DX
POP BX ;RETURN EOL
GC1:
RET
;
;
;
; cget(unit)
;
;
CGET:
POP CX
POP BX
MOV DX,BX
PUSH BX
PUSH CX
PUSH DS
MOV AX,DATASEG
MOV DS,AX
MOV AL,EOFFLG
AND AL,[BX]+FLAG ;END OF FILE EXIST?
JZ CG1 ;NOPE
CG0:
POP DS
MOV BX,-1 ;ERROR RETURN
RET
CG1:
MOV AX,[BX]+FCBSIZE+NEXTP ;BUFFER OFFSET OF NEXT CHARACTER
MOV CX,[BX]+FCBSIZE+UNUSED ;NUM CHARS REMAINING IN BUF
OR CX,CX
JNZ CG2 ;SOME LEFT
;READ NEW SECTOR
MOV AX,SEQREAD
PUSH AX ;FUNCTION
PUSH DX ;UNIT
CALL PCDOSIO ;READ SECTOR
POP DX
POP AX
OR BH,BL ;OK?
JNZ CG0 ;JUMP IF NOT
MOV BX,DX ;RESTORE UNIT
MOV CX,BUFSIZ ;NEW COUNT
MOV AX,DX
ADD AX,FCBSIZE+BUFFER ;NEW NEXT CHAR OFFSET
CG2:
DEC CX ;REDUCE UNUSED
MOV [BX]+FCBSIZE+UNUSED,CX
MOV CX,AX
INC CX ;BUMP UP NEXT CHAR POINTER
MOV [BX]+FCBSIZE+NEXTP,CX
MOV BX,AX ;OFFSET OF CHAR TO RETURN
MOV AL,[BX]
CMP AL,CTRLZ ;IS IT EOF MARKER?
JNZ CG3 ;JUMP IF NOT
MOV BX,DX ;UNIT
MOV AH,EOFFLG
OR [BX]+FLAG,AH ;SET END OF FILE IN FCB
JMP CG0
CG3:
MOV BL,AL ;CHAR TO RETURN
XOR BH,BH
POP DS
RET
;
;
;
; putc(char,unit)
;
;
;
PUBLIC QZPUTC
QZPUTC:
POP CX
POP BX ;UNIT
POP AX ;CHAR
PUSH AX
PUSH BX
PUSH CX
PUSH AX ;CHAR
PUSH BX ;UNIT
CALL CPUT ;PUT OUT CHAR
POP DX ;UNIT
;LEAVE CHAR ON STACK AS RETURN VALUE
OR BH,BH ;ERROR?
JS PC2 ;JUMP IF SO
CMP BL,EOL ;DID EOL GO OUT?
JNZ PC1 ;JUMP IF NOT
MOV AX,LF ;PUT OUT LF ALSO
PUSH AX
PUSH DX
CALL CPUT
POP DX
POP AX
OR BH,BH ;ERROR?
JS PC2 ;JUMP IF SO
PC1:
POP BX ;RETURN CHAR PASSED IN
RET
PC2:
POP CX ;CLEAR CHAR OFF STACK
MOV BX,-1 ;ERROR RETURN
RET
;
;
;
; cput(c,unit)
;
;
CPUT:
POP CX
POP BX ;UNIT
POP SI ;CHAR
PUSH SI
PUSH BX
PUSH CX
PUSH DS
MOV AX,DATASEG
MOV DS,AX
MOV DX,BX
MOV AX,[BX]+FCBSIZE+NEXTP ;NEXT CHAR OFFSET
MOV CX,[BX]+FCBSIZE+UNUSED ;UNUSED CHAR COUNT
OR CX,CX
JNZ CP2 ;JUMP IF ROOM AVAILABLE
MOV AX,SEQWRITE
PUSH AX ;FUNCTION
PUSH DX ;UNIT
CALL PCDOSIO ;SECTOR WRITE
POP DX
POP AX
OR BH,BL
JZ CP1 ;JUMP IF OK
CP0:
POP DS
MOV BX,-1 ;ERROR RETURN
RET
CP1:
MOV CX,BUFSIZ
MOV AX,DX
ADD AX,FCBSIZE+BUFFER
MOV BX,DX
CP2:
DEC CX ;REDUCE UNUSED
MOV [BX]+FCBSIZE+UNUSED,CX
MOV CX,AX
INC CX
MOV [BX]+FCBSIZE+NEXTP,CX ;NEW NEXT CHAR OFFSET
MOV BX,AX
MOV AX,SI ;CHAR TO PUT
MOV [BX],AL ;BUFFER CHARACTER
MOV BX,AX
POP DS
RET
;
CSEG ENDS
STACK SEGMENT BYTE PUBLIC 'stack'
STACK ENDS
DUMMY SEGMENT BYTE STACK 'dummy'
DB 128 DUP(?)
DUMMY ENDS
END CCGO
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/