|
DataMuseum.dkPresents historical artifacts from the history of: CP/M |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about CP/M Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - download
Length: 13952 (0x3680) Types: TextFile Names: »DEFF2A.CSM«
└─⟦1275f6521⟧ Bits:30005823 BD Software C Compiler v1.50a └─ ⟦this⟧ »DEFF2A.CSM« └─⟦b35f94715⟧ Bits:30003295 BDS C version 1.50 arbejdsdiskette til RC703 Piccolo └─⟦b35f94715⟧ Bits:30005324 BDS C version 1.50 arbejdsdiskette til RC703 Piccolo └─ ⟦this⟧ »DEFF2A.CSM«
; ; BD Software C Compiler v1.50 ; Standard Library Machine Language Functions (part A) ; Copyright (c) 1982 by Leor Zolman ; ; This file is in "CSM" format; to convert to CRL format, ; use CASM.SUB in conjunction with CASM.COM, ASM.COM and DDT.COM. ; ; Functions appearing in this file: ; ; getchar kbhit ungetch putchar putch gets rand srand ; srand1 nrand csw setmem movmem call calla inp ; outp peek poke sleep pause exit bdos bios ; biosh codend externs endext topofmem exec execv ; sbrk rsvstk memcmp ; INCLUDE "bds.lib" FUNCTION getchar lda ungetl ;any character pushed back? ora a mov l,a jz gch2 xra a ;yes. return it and clear the pushback sta ungetl ;byte in C.CCC. mvi h,0 ret gch2: push b mvi c,conin call bdos pop b cpi cntrlc ;control-C ? jz exit ;if so, exit the program. cpi 1ah ;control-Z ? lxi h,-1 ;if so, return -1. rz mov l,a cpi cr ;carriage return? jnz gch3 push b mvi c,conout ;if so, also echo linefeed mvi e,lf call bdos pop b mvi l,newlin ;and return newline (linefeed).. gch3: mvi h,0 ret ENDFUNC FUNCTION kbhit lda ungetl ;any character ungotten? mvi h,0 mov l,a ora a rnz ;if so, return true push b mvi c,cstat ;else interrogate console status call bdos pop b ora a ;0 returned by BDOS if no character ready lxi h,0 rz ;return 0 in HL if no character ready inr l ;otherwise return 1 in HL ret ENDFUNC kbhit FUNCTION ungetch lda ungetl mov l,a push h call ma2toh sta ungetl pop h mvi h,0 ret ENDFUNC ungetch FUNCTION putchar call ma1toh ;get character in A push b mvi c,conout cpi newlin ;newline? jnz put1 ;if not, just go put out the character mvi e,cr ;else...put out CR-LF call bdos mvi c,conout mvi a,lf put1: mov e,a call bdos put2: mvi c,cstat ;now, is input present at the console? call bdos ora a jnz put3 pop b ;no...all done. ret put3: mvi c,conin ;yes. sample it (this will always echo the call bdos ; character to the screen, alas) cpi cntrlc ;is it control-C? jz exit ;if so, abort and reboot pop b ;else ignore it. ret ENDFUNC FUNCTION putch call ma1toh push b mvi c,conout mov e,a cpi newlin jnz putch1 ;if not newline, just put it out mvi e,cr ;else put out CR-LF call bdos mvi c,conout mvi e,lf putch1: call bdos pop b ret ENDFUNC FUNCTION gets call ma1toh ;get destination address push b ;save BC push h push h lxi h,-150 ;use space below stack for reading line dad sp push h ;save buffer address mvi m,88h ;Allow a max of about 135 characters mvi c,getlin xchg ;put buffer addr in DE call bdos ;get the input line mvi c,conout mvi e,lf ;put out a LF call bdos pop h ;get back buffer address inx h ;point to returned char count mov b,m ;set B equal to char count inx h ;HL points to first char of line pop d ;DE points to start destination area copyl: mov a,b ;copy line to start of buffer ora a jz gets2 mov a,m stax d inx h inx d dcr b jmp copyl gets2: xra a ;store terminating null stax d pop h ;return buffer address in HL pop b ret ENDFUNC FUNCTION rand lhld rseed xchg mvi a,48h ana e jz rand1 jpe rand1 stc rand1: lhld rseed+2 mov a,h ral mov h,a mov a,l ral mov l,a shld rseed+2 mov a,d ral mov h,a mov a,e ral mov l,a shld rseed mov a,h ani 7fh mov h,a ret ENDFUNC FUNCTION srand call ma1toh mov a,h ora l jz srand2 shld rseed shld rseed+2 ret srand2: lxi d,stg1 push b mvi c,9 call bdos lxi h,0bdbdh srand3: push h mvi c,11 call bdos pop h inx h inx h inx h ani 1 jz srand3 shld rseed shld rseed+2 mvi c,conout mvi e,cr call bdos mvi c,conout mvi e,lf call bdos mvi c,conin ;clear the character call bdos pop b ret stg1: db 'Wait a few seconds, and type a CR: $' ENDFUNC FUNCTION srand1 EXTERNAL puts call ma1toh push h call puts ;print prompt string pop h push b lxi h,5678h sr1a: push h mvi c,cstat call bdos pop h inx h inx h inx h ora a jz sr1a shld rseed shld rseed+2 pop b ret ENDFUNC FUNCTION nrand EXTERNAL puts call arghak lhld arg1 ;get n (1st arg) mov a,h ana l cpi 255 ;was it -1 (set seed) ? jnz nrand1 lhld arg2 ;copy seed shld seed lhld arg3 shld seed+2 lhld arg4 shld seed+4 ret ;all done nrand1: push b mov a,h ;look at first arg again ora l jnz nrand3 ;is it 0 (randomize)? lhld arg2 push h ;yes. print out string call puts ;call puts pop d lxi h,5a97h ;yes. start w/something odd nrand2: push h mvi c,cstat ;interrogate console status call bdos pop h inx h ;and keep it odd inx h ;and growing ora a jz nrand2 ;until user types something. shld seed ;then plaster the value all over the shld seed+2 ;seed. shld seed+4 pop b ret nrand3: lda seed ;now compute next random number. from this ori 1 ; point on, the code is that of Prof. Paul Gans sta seed ;lsb of SEED must be 1 mvi b,6 ;clear 6 PROD bytes to 0 lxi h,prod randm1: mvi m,0 inx h dcr b jnz randm1 lxi b,6 ;set byte counter randm2: lxi h,plier-1 dad b ;make addr of lsb of PLIER mov a,m ;PLIER byte push b ;save byte counter mvi b,8 ;set bit counter randm3: mov d,a ;save PLIER byte lxi h,prod ;shift whole PROD left one bit mvi c,6 xra a randm4: mov a,m ;get byte ral ;shift left mov m,a ;put byte inx h dcr c jnz randm4 mov a,d ;recover PLIER byte ral ;look at current high bit jnc randm6 ;0 means no add cycle push psw ;add SEED to PROD xra a mvi c,6 lxi h,prod lxi d,seed randm5: ldax d adc m mov m,a inx h inx d dcr c jnz randm5 pop psw randm6: dcr b ;test bit counter jnz randm3 ;go cycle more bits pop b ;recover byte counter dcr c ;test it jnz randm2 ;go process more bytes mvi b,6 ;complement PROD, add 1 to it, lxi h,seed ;and transfer it to SEED. lxi d,prod xra a cmc randm7: ldax d cma aci 0 mov m,a inx h inx d dcr b jnz randm7 dcx h ;put the two high order bytes mov a,m ;into HL for return to C, not ani 7fh ;neglecting to zero the high mov h,a ;order bit so a positive int lda seed+4 ;is returned mov l,a pop b ret plier: db 0c5h,87h,1 db 0eh,9ah,0e0h seed: db 1,0,0,0,0,0 prod: db 0,0,0,0,0,0 ENDFUNC FUNCTION csw in 255 mov l,a mvi h,0 ret ENDFUNC FUNCTION setmem call arghak push b lhld arg2 xchg lhld arg1 lda arg3 mov c,a inx d setm2: dcx d mov a,d ora e jnz setm3 pop b ret setm3: mov m,c inx h jmp setm2 ENDFUNC FUNCTION movmem call arghak lhld arg3 ;get block length mov a,h ora l rz ;do nothing if zero length push b mov b,h mov c,l ;set BC to length lhld arg2 ;get dest addr xchg ;put in DE lhld arg1 ;get source addr in HL call cmphd ;if source < dest, do tail-first jc tailf ;else do head-first headf: mvi a,2 ;test for Z-80 inr a jpe m8080h ;Z80? db 0edh,0b0h ;yes. do block move. pop b ret ;and done. m8080h: mov a,m stax d inx h inx d dcx b mov a,b ora c jnz m8080h pop b ret tailf: dcx b ;tail first. Compute new source dad b ;and destination addresses xchg dad b xchg inx b mvi a,2 ;test for Z80 inr a jpe m8080t ;Z80? db 0edh,0b8h ;yes. do block move. pop b ret m8080t: mov a,m stax d dcx h dcx d dcx b mov a,b ora c jnz m8080t pop b ret cmphd: mov a,h cmp d rnz mov a,l cmp e ret ENDFUNC FUNCTION call call arghak push b lhld arg5 xchg lhld arg4 mov b,h mov c,l lda arg2 lxi h,call2 push h lhld arg1 push h lhld arg3 ret call2: pop b ret ENDFUNC FUNCTION calla call arghak push b lhld arg5 ;get de value xchg lhld arg4 ;get bc value mov b,h mov c,l lda arg2 ;get a value lxi h,calla2 ;get return address push h ;push it lhld arg1 ;get address of routine push h lhld arg3 ;get hl value ret ;call routine calla2: mov l,a ;put A value in HL mvi h,0 ;clear high byte pop b ret ENDFUNC FUNCTION inp call ma1toh sta iohack+1 ;store as arg to ram area input subroutine call iohack ;call the subroutine to get value mov l,a ;and put into HL mvi h,0 ret ENDFUNC FUNCTION outp call ma1toh ;get port number sta iohack+4 ;store as arg to ram area output subroutine call ma2toh ;get data byte call iohack+3 ;output it ret ENDFUNC FUNCTION peek peek: call ma1toh mov l,m mvi h,0 ret ENDFUNC peek FUNCTION poke call arghak lhld arg1 lda arg2 mov m,a ret ENDFUNC FUNCTION sleep call ma1toh push b inx h sl1: dcx h mov a,h ora l jnz sl1a pop b ret sl1a: lxi d,10000 sl2: dcx d mov a,d ora e jnz sl2 push h mvi c,cstat call bdos ora a pop h jz sl1 push h mvi c,conin call bdos cpi cntrlc jz exit pop h jmp sl1 ENDFUNC FUNCTION pause push b paus1: mvi c,cstat call bdos ora a jz paus1 pop b ret ENDFUNC FUNCTION exit jmp exit ENDFUNC FUNCTION bdos call arghak push b lda arg1 ;get C value mov c,a lhld arg2 ;get DE value xchg ;put in DE call bdos ;make the bdos call pop b ret ;and return to caller ENDFUNC FUNCTION bios call arghak push b lhld base+1 ;get addr of jump table + 3 dcx h ;set to addr of first jump dcx h dcx h lda arg1 ;get function number (1-85) mov b,a ;multiply by 3 add a add b mov e,a ;put in DE mvi d,0 dad d ;add to base of jump table push h ;and save for later lhld arg2 ;get value to be put in BC mov b,h ;and put it there mov c,l lxi h,retadd ;where call to bios will return to xthl ;get address of vector in HL pchl ;and go to it... retadd: mov l,a ;all done. now put return value in HL mvi h,0 pop b ret ;and return to caller ENDFUNC FUNCTION biosh call arghak push b lhld base+1 ;get addr of jump table + 3 dcx h ;set to addr of first jump dcx h dcx h lda arg1 ;get function number (1-85) mov b,a ;multiply by 3 add a add b mov e,a ;put in DE mvi d,0 dad d ;add to base of jump table push h ;and save for later lhld arg2 ;get value to be put in BC mov b,h ;and put it there mov c,l lhld arg3 ;get value to be put in DE mov d,h ;adn put it there mov e,l lxi h,retadd ;where call to bios will return to xthl ;get address of vector in HL pchl ;and go to it... retadd: pop b ;all done. Leave return value in HL ret ;and return to caller ENDFUNC FUNCTION codend lhld codend ret ENDFUNC FUNCTION externs lhld extrns ret ENDFUNC FUNCTION endext lhld freram ret ENDFUNC FUNCTION topofmem lhld base+6 lda tpa ;check for "NOBOOT" hackery cpi 0c3h ; "jmp" at start of C.CCC (as inserted by "-n")? dcx h ;if CCC doesn't begin with "lxi h," then top of rnz ;memory is just below the base of the bdos lxi d,-2100 ;else subtract CCP size (plus little more for good dad d ;measure) and return that as top of memory. ret ENDFUNC FUNCTION exec EXTERNAL execl call ma1toh ;get filename lxi d,0 ;load null parameter in DE push d ;push null parameter push h ;push filename call execl ;do an execl pop d ;clean up stack pop d ret ENDFUNC FUNCTION execv EXTERNAL execl call arghak push b ;save BC lhld arg2 ;get -> arg list mvi b,0 ;clear arg count execv1: inr b ;bump arg count mov e,m inx h mov d,m inx h mov a,d ora e ;last arg? jnz execv1 ;if not, keep looking for last one mov a,b ;save arg count in case of error sta savcnt dcx h ;HL -> next to last arg execv2: mov d,m ;now push args on stack dcx h mov e,m dcx h dcr b push d jnz execv2 execv3: lhld arg1 ;get program name push h ;save as first arg to execl call execl ;go do it; shouldn't come back. lda savcnt ;woops, we're back. Must've been an error... inr a ;bump to take prog name into consideration add a mov l,a ;put size of passed parameter list mvi h,0 ;into HL, and adjust stack dad sp sphl pop b ;restore BC lxi h,-1 ;return error value ret savcnt: ds 1 ;save arg count here ENDFUNC FUNCTION sbrk call ma1toh ;get # of bytes needed in HL xchg ;put into DE lhld allocp ;get current allocation pointer push h ;save it dad d ;get tentative last address of new segment jc brkerr ;better not allow it to go over the top! dcx h xchg ; now last addr is in DE lhld alocmx ;get safety factor mov a,h ;negate cma mov h,a mov a,l cma mov l,a inx h dad sp ;get HL = (SP - alocmx) call cmpdh ;is DE less than HL? jnc brkerr ;if not, can't provide the needed memory. xchg ;else OK. inx h shld allocp ;save start of next area to be allocated pop h ;get pointer to this area ret ;and return with it. brkerr: pop h ;clean up stack jmp error ;and return with -1 to indicate can't allocate. cmpdh: mov a,d cmp h rc rnz mov a,e cmp l ret ENDFUNC FUNCTION rsvstk call ma1toh ;get the value to reserve shld alocmx ;and set new safety factor ret ENDFUNC FUNCTION memcmp call ma3toh ;get length in HL push b ;save BC mov b,h mov c,l ;move length to BC call ma3toh ;get block2 address in HL xchg ;move to DE call ma2toh ;get block1 address in HL loop: mov a,b ;all done? ora c jnz loop1 lxi h,1 ;if so, return TRUE, for perfect match pop b ret loop1: dcx b ;decrement count ldax d ;get block2 byte cmp m ;compare to block1 byte inx d ;bump pointers inx h jz loop ;if so far so good, go on comparing lxi h,0 ;else a mismatch pop b ret ENDFUNC«eof»