home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
vol_200
/
223_02
/
ulink.mac
< prev
next >
Wrap
Text File
|
1989-02-23
|
6KB
|
253 lines
; ulink
;
; Small-C System Library Version 1.0
;
; by
;
; Fred A. Scacchitti
; 25 Glenview Lane
; Roch., NY 14609
;
; 11 - 24 - 84
;
; This module is a derivative of RUNTIME.MAC by Glen Fisher
; and Bill Randle. It contains a minimal implementation of
; CP/M hooks to allow proper linking of Small-C programs
; compiled by Version 2.08 (and later) of the Small-C compiler.
;
; This module contains the following routines:
;
; -ULINK entry point just like J. E. Hendrix Vers. 2.1
;
; -Initialization of stack, memory buffers, and argument
; passing (argv, argc).
;
;
; call to main()
; links to main in user program
;
; -Cleans house and returns to CP/M
;
;
;
;
; Now then here's the starting code
;
;
;
; 1st - Save CPM's stack pointer, establish file i/o constructs set
; new default buffer and establish start of available memory.
;
; 2nd - Get the default disk and set stack at base of BDOS or CCP
; depending on the status ZZZCCP. 0 = bdos 1 = ccp
;
; 3rd - Parse the CPM input line and modify it so that we can pass
; the C program in the argc, argv form that it expects.
; HL = pointer to next argv entry
; DE = pointer to next character in command line
; B = number of characters left in line
; C = argument count (argc)
;
; 4th - Call MAIN to commence operation of the user program
;
; 5th - Work, work, work and then return to here via exit(), abort()
; or normal return from program.
;
; 6th - Close any open files (buffers are not flushed)
;
; 7th - Restore CP/M's stack pointer, select the disk you entered
; with, reset the default buffer and return to CP/M either
; via a JMP 0 (ZZZCCP = 0) or RET (ZZZCCP = 1).
;
;
CBDOS EQU 5 ;/* bdos entry point */
CPMARG EQU 128 ;/* CP/M command line */
MAXARG EQU 24 ;/* Maximum number of input args */
STDIN EQU 0
STDOUT EQU 1
STDERR EQU 2
STDLST EQU 4
CBDOS EQU 5
CLOSE EQU 16
;
FCBSIZE EQU 36 ;size, in bytes, of an FCB
BUFFER EQU 6 ;offset to disk sector buf. in I/O struct.
UNGOT EQU 5 ;offset to char ungotten by ungetc()
FLAG EQU 33 ;file-type flag byte (in unused part of FCB)
FREEFLG EQU 128 ;This I/O structure is available
BUFSIZ EQU 1024 ;how long the sector buffer is
NBUFS EQU 8 ;number of I/O buffers
TBUFSZ EQU 128 ;size of default disk buffer
;
EXTRN MAIN, ZZBUF, ZZZCCP
;
;
ULINK::
;
LXI H,0 ; get CPM's stack pointer
DAD SP
SHLD ZZSTAK ; save it for later
;
MVI C,26
LXI D,ZZBUF
CALL CBDOS ; Set the default buffer out there
;
SETIO:
MVI B,NBUFS
LXI H,ZZBUF+TBUFSZ+FLAG
LXI D,FCBSIZE+BUFFER+BUFSIZ
MVI A,FREEFLG
SETIO2: MOV M,A ;set all buffers to free
DAD D ;on to next buffer
DCR B
JNZ SETIO2 ;if there is one...
SHLD ZZMEM ;put it where it belongs
;
MVI C,25 ; get logged-in disk
CALL CBDOS
INR A
STA ZZDFLT ; save it
;
LDA CBDOS+2 ; get base of BDOS
MOV H,A ; save page in HL
MVI L,0 ; where do we put the stack
;
LDA ZZZCCP ; let's check
ORA A ;
JZ SETSTK ; just below the BDOS
MOV A,H
SUI 8 ; just below the CCP
MOV H,A
;
SETSTK:
SPHL ; set stack pointer
;
MVI C,0 ; Init argc
LXI H,ARGV ; Pointer to first entry of argv array
;
; CPM does not tell us what the first word of the command
; line was (the name of pgm), so we fake it by pointing it
; to an ascii string with '*' in it
;
LXI D,PGM ; Pointer to 'pgmname' string
CALL SVARG ; Save next argument
;
; Ok, now for the real stuff. Set DE pair to point to
; CPM command line and start searching for arguments
LXI D,CPMARG ; Pointer to CPM arg line
LDAX D ; Load # character in line
MOV B,A ; Save it in B
NXTSP: INX D ; Point to next character
DCR B ; Decrement character count
JM ENDCMD ; End of cmd line
LDAX D ; Load next character in line
CPI ' ' ; Space?
JZ NXTSP ; Yes...continue searching
CALL SVARG ; Nope, save starting point of this arg
; Loop looking for either end of line of a space
NXTCH: INX D ; Point to next character
DCR B ; Decrement character count
JM ENDWRD ; End of cmd line, but need to end arg
LDAX D ; Load next character in line
CPI ' ' ; Space?
JNZ NXTCH ; Nope...keep looking
MVI A,0 ; Yes, replace it with a zero byte
STAX D
JMP NXTSP ; Look for start of next arg
ENDWRD: MVI A,0
STAX D
ENDCMD: MVI B,0 ; Zero B (BC now is 16 bit argc)
PUSH B ; First arg to main procedure
LXI H,ARGV ; Point to argv array
PUSH H ; Second argument to main procedure
MVI A,2 ; Load up the argument count
;
CALL MAIN ; Transfer to the C world....
;
; anchors
; away
; my
; bo
; y
; y
; y
; y
; y
;
EXIT::
MVI B,NBUFS ; Prepare to scan for open files
MVI C,CLOSE
LXI H,ZZBUF+TBUFSZ+FLAG
LXI D,FCBSIZE+BUFFER+BUFSIZ
SCANEM:
MOV A,M ; Get free flag
CPI FREEFLG ; Is it free ?
JZ NOPEN ; Yes - not open, go get next
PUSH B ; No - prepare to close
PUSH D
PUSH H
LXI D,-FLAG
DAD D
XCHG ; DE --> Start of FCB
CALL CBDOS ; Close the file
POP H ; Restore scan setup
POP D
POP B
NOPEN:
DAD D ; Point to next flag
DCR B ; Last one ?
JNZ SCANEM ; No - keep scanning until done
;
MVI C,26
LXI D,80H
CALL CBDOS ; Reset the default buffer
;
LHLD ZZSTAK ; Load stack pointer
SPHL
LDA ZZZCCP ; How do we get back ?
ORA A
RNZ ; this way to CCP
;
; or
;
; this way to warm boot
;
LDA ZZDFLT ; Grab orig. logged-in disk
MOV E,A
DCR E ; (cvt. back to 0-n)
MVI C,14 ; and log it in again
CALL CBDOS ; (mod to cbdos (fas))
;
JMP 0
;
;
SVARG: MOV M,E ; Save pointer to start of string
INX H
MOV M,D
INX H
INR C ; Increment argc
RET
PGM: DB '*',0
;
ARGV: DS MAXARG*2
;
ZZDFLT:: DB 0 ; default disk
;
ZZSTAK:: DW 0 ; CP/M's stack
;
ZZMEM:: DW 0 ; useable memory pointer
;
ZZTEMP:: DW 0 ; available to anyone
;
;
;
END ULINK