; T i n y C li b r a r y ; ;Fetch a single byte from the address in HL and ; sign extend into HL ccgchar: MOV A,M ccsxt: MOV L,A RLC SBB A MOV H,A RET ;Fetch a full 16-bit integer from the address in HL ccgint: MOV A,M INX H MOV H,M MOV L,A RET ;Store a single byte from HL at the address in DE ccpchar: MOV A,L STAX D RET ;Store a 16-bit integer in HL at the address in DE ccpint: MOV A,L STAX D INX D MOV A,H STAX D RET ;Inclusive "or" HL and DE into HL ccor: MOV A,L ORA E MOV L,A MOV A,H ORA D MOV H,A RET ;Exclusive "or" HL and DE into HL ccxor: MOV A,L XRA E MOV L,A MOV A,H XRA D MOV H,A RET ;"And" HL and DE into HL ccand: MOV A,L ANA E MOV L,A MOV A,H ANA D MOV H,A RET ;Test if HL = DE and set HL = 1 if true else 0 cceq: CALL cccmp RZ DCX H RET ;Test if DE != HL ccne: CALL cccmp RNZ DCX H RET ;Test if DE > HL (signed) ccgt: XCHG CALL cccmp RC DCX H RET ;Test if DE <= HL (signed) ccle: CALL cccmp RZ RC DCX H RET ;Test if DE >= HL (signed) ccge: CALL cccmp RNC DCX H RET ;Test if DE < HL (signed) cclt: CALL cccmp RC DCX H RET ;Common routine to perform a signed compare ; of DE and HL ;This routine performs DE - HL and sets the conditions: ; Carry reflects sign of difference (set means DE < HL) ; Zero/non-zero set according to equality. cccmp: MOV A,E SU L MOV E,A MOV A,D SBB H LXI H,1 ;preset true condition JM cccmp1 ORA E ;"OR" resets carry RET cccmp1: ORA E STC ;set carry to signal minus RET ; ;Test if DE >= HL (unsigned) ccuge: CALL ccucmp RNC DCX H RET ; ;Test if DE < HL (unsigned) ccult: CALL ccucmp RC DCX H RET ; ;Test if DE > HL (unsigned) ccugt: XCHG CALL ccucmp RC DCX H RET ; ;Test if DE <= HL (unsigned) ccule: CALL ccucmp RZ RC DCX H RET ; ;Common routine to perform unsigned compare ;carry set if DE < HL ;zero/nonzero set accordingly ccucmp: MOV A,D CMP H JNZ $+5 MOV A,E CMP L LXI H,1 RET ; ;Shift DE arithmetically right by HL and return in HL ccasr: XCHG MOV A,H RAL MOV A,H RAR MOV H,A MOV A,L RAR MOV L,A DCR E JNZ ccasr+1 RET ;Shift DE arithmetically left by HL and return in HL ccasl: XCHG DAD H DCR E JNZ ccasl+1 RET ;Subtract HL from DE and return in HL ccsub: MOV A,E SUB L MOV L,A MOV A,D SBB H MOV H,A RET ;Form the two's complement of HL ccneg: CALL cccom INX H RET ;Form the one's complement of HL cccom: MOV A,H CMA MOV H,A MOV A,L CMA MOV L,A RET ;Multiply DE by HL and return in HL ccmult: MOV B,H MOV C,L LXI H,0 ccmult1: MOV A,C RRC JNC $+4 DAD D XRA A MOV A,B RAR MOV B,A MOV A,C RAR MOV C,A ORA B RZ XRA A MOV A,E RAL MOV E,A MOV A,D RAL MOV D,A ORA E RZ JMP ccmult1 ;Divide DE by HL and return quotient in HL, remainder in DE ccdiv: MOV B,H MOV C,L MOV A,D XRA B PUSH PSW MOV A,D ORA A CM ccdeneg MOV A,B ORA A CM ccbcneg MVI A,16 PUSH PSW XCHG LXI D,0 ccdiv1: DAD H CALL ccrdel JZ ccdiv2 CALL cccmpbcde JM ccdiv2 MOV A,L ORI 1 MOV L,A MOV A,E SUB C MOV E,A MOV A,D SBB B MOV D,A ccdiv2: POP PSW DCR A JZ ccdiv3 PUSH PSW JMP ccdiv1 ccdiv3: POP PSW RP CALL ccdeneg XCHG CALL ccdeneg XCHG RET ccdeneg: MOV A,D CMA MOV D,A MOV A,E CMA MOV E,A INX D RET ccbcneg: MOV A,B CMA MOV B,A MOV A,C CMA MOV C,A INX B RET ccrdel: MOV A,E RAL MOV E,A MOV A,D RAL MOV D,A ORA E RET cccmpbcde: MOV A,E SUB C MOV A,D SBB B RET ; ;I/O subroutines ; ;Input a character into HL INCH: CALL WH0 ;Get one JMP ccsxt ;Sign extend ; ;Output a character (OUTCH(char)) OUTCH: LXI H,2 DAD SP ;index past return MOV A,M ;get char CALL WH1 JMP ccsxt ; ;Test for a character(return in HL if found,but don't dequeue) CHRDY: LHLD KBIG LDA KBIP SUB L JZ CHRDY1 MOV A,M CHRDY1: JMP ccsxt ; ;Disk file I/O ; FDENUM EQU 4 ;Number files supported at once FDESIZE EQU 310 ;Number bytes required for each file ; ;Offsets into unit tables FDISKADD EQU 45 FSECTCNT EQU 47 FBYTEOFF EQU 49 FBUFF EQU 50 ; ;Open a file ;Call: FOPEN(direction,unit,size,nameptr) ; direction = 1 to read, 2 to write ; unit = 1, 2, 3, ...(# units avail) ; size = max size (ignored) ; nameptr = addr of asciz filename ;Returns: 0=good open, -1=open failure ; FOPEN: LXI H,2 DAD SP ;ptr to arg list LXI D,FOPARGS MVI C,8 FOP1: MOV A,M STAX D INX H INX D DCR C JNZ FOP1 ;transfer args to usable area CALL FOPFDE ;get unit's block JC FOPERR MOV A,M ;idle? ORA A JNZ FOPERR XRA A STA NFDIR ;force directory load LHLD FILENAME XCHG LXI H,FFILE MVI C,0FFH FOPEN1: LDAX D ;Get filename MOV M,A INX H INX D INR C ORA A JNZ FOPEN1 MOV A,C ORA A JZ FOPERR ;Null DCX H MVI M,0DH ;append LHLD FDE INX H XCHG ;DE = FDE addr LXI H,FFILE LXI B,'TX' MVI A,60H CALL Ovrto DB 'Gfid' PUSH PSW LDA FTYPE DCR A JNZ FOPWRITE ;Read open POP PSW JC FOPERR JMP FOPOK ;Write open FOPWRITE: POP PSW JNC FOPERR LXI H,0300H CALL cccmp ;Was it error 300? JNZ FOPERR ;did not exist...good. LHLD FDE INX H MOV A,M ANI 3 ;get drive # MOV D,A MVI E,0 LXI H,FDEBUFF LXI B,FDESIZE MVI A,(FDENUM AND 0FFH) FOPWRT1: PUSH PSW MOV A,M CPI 2 JNZ FOPWRT2 INX H MOV A,M DCX H ANI 3 CMP D ;any other writes on this drive? JNZ FOPWRT2 INR E FOPWRT2: DAD B POP PSW DCR A JNZ FOPWRT1 MOV A,E ORA A JNZ FOPERR ;yes...fail ;File looks ok FOPOK: LHLD FDE INX H INX H MOV A,M INR A INR A INR A ANI 01FH MOV C,A MVI B,0 DAD B XCHG ;DE = @FDA LHLD FDE LXI B,FDISKADD DAD B MVI C,4 FOPOK1: LDAX D MOV M,A ;copy FDA & DNS INX H INX D DCR C JNZ FOPOK1 XRA A MOV M,A ;clear byte offset FOPOK2: INX H MVI M,0 DCR A JNZ FOPOK2 ;clear buffer LHLD FDE LXI B,FDISKADD DAD B MOV E,M INX H MOV D,M XCHG LXI D,350 MOV A,H CMP D JNZ FOPOK3 MOV A,L CMP E FOPOK3: JNC FOPERR ;At end of disk LHLD FDE LDA FTYPE MOV M,A ;declare open LXI H,0 RET FOPERR: LXI H,-1 ;open error RET ; ;Find the unit block for unit in FUNIT ;carry set on error FOPFDE: LDA FUNIT MVI B,(FDENUM AND 0FFH) LXI D,FDESIZE LXI H,FDEBUFF FOPFDE1: DCR A JZ FOPFDE2 DAD D DCR B JNZ FOPFDE1 STC ;error RET FOPFDE2: SHLD FDE STC CMC RET ; ;Close a file ;Call: FCLOSE(unit) ;no returned value FCLOSE: LXI H,2 DAD SP MOV A,M ;get unit STA FUNIT CALL FOPFDE RC MOV A,M CPI 2 CZ FCLSWT ;write need special close LHLD FDE MVI M,0 RET ; ;Close an output file ;carry set if error FCLSWT: LHLD FDE LXI B,FBYTEOFF DAD B MOV A,M ORA A JZ FCLSWT2 LXI H,FZERO SHLD FMEM ;set ptr to... MVI M,0 ;a known null word CALL FWRTB ;empty system buffer JNC FCLSWT FCLSWT2: LHLD FDE LXI B,FSECTCNT DAD B MOV E,M INX H MOV D,M DCX H MOV A,E ORA D STC CMC RZ ;nothing written PUSH D ;DNS LHLD FDE INX H INX H MOV A,M INR A INR A INR A ANI 01FH MOV C,A MVI B,0 DAD B INX H INX H ;HL = @DNS POP D MOV M,E INX H MOV M,D ;put in FDE LHLD FDE INX H MVI A,1 CALL Ovrto DB 'Gfid' RET ; ;Read from a file ;Call: FREAD(memaddr,bytes,unit) ; memaddr = beginning addr of user buffer ; bytes = positive number of bytes to read ;Returns: -1 = error in read ; else returns number of bytes successfully read ; (ie 0 = end of file) FREAD: CALL FXARGS LXI H,0 SHLD FXFER ;preset xfer cnt CALL FOPFDE JC FXFERR MOV A,M DCR A JNZ FXFERR ;Main read loop FREAD1: LHLD FCNT MOV A,H ORA L JZ FXOK ;done MOV A,H ORA A JNZ FREAD3 ;less than 256 CALL FREADB ;read a byte JC FXFERR JMP FREAD1 ;and loop till done ;More than 256 means we go direct to user memory FREAD3: LHLD FDE LXI B,FBYTEOFF DAD B MOV A,M ORA A JZ FREAD5 CALL FREADB ;we have some in system buff first JC FXFERR JMP FREAD1 FREAD5: LHLD FDE LXI B,FSECTCNT DAD B MOV E,M INX H MOV D,M ;DE = # sectors left LDA FCNT+1 ;get msb # bytes MVI H,0 ;HL = # sectors requested MOV A,H CMP D JNZ FREAD6 MOV A,L CMP E FREAD6: JC FREAD7 XCHG ;user wants too many FREAD7: MOV A,H ORA L JZ FXOK ;if zero...done PUSH H ;save # to read MOV A,L ;(# < 256) PUSH PSW LHLD FDE INX H MOV A,M ANI 3 MOV C,A ;unit MVI B,1 ;read cmd LXI D,FDISKADD-1 DAD D MOV E,M INX H MOV D,M ;DE = disk addr LHLD FMEM ;HL = mem addr XCHG POP PSW CALL Dio ;read POP H ;# attempted JC FXFERR ;good read XCHG ;DE = # sectors read LHLD FDE LXI B,FDISKADD DAD B MOV A,E ADD M MOV M,A INX H MOV A,D ADC M MOV M,A ;bump ahead disk addr INX H MOV A,M SUB E MOV M,A INX H MOV A,M SBB D MOV M,A ;count off # sectors LHLD FMEM MOV B,E MVI C,0 ;make # bytes DAD B SHLD FMEM ;bump ahead mem addr LHLD FXFER DAD B SHLD FXFER ;& # bytes read MOV A,B CMA MOV B,A MOV A,C CMA MOV C,A INX B LHLD FCNT DAD B SHLD FCNT ;count down # bytes JMP FREAD1 ;loop ; ;Read a single byte into user's memory ;carry set if error FREADB: LHLD FDE LXI B,FBYTEOFF DAD B MOV A,M ORA A JNZ FRDBYT ;nothing in system buffer DCX H MOV A,M DCX H ORA M ;any left? JZ FRDBX ;no DCX H MOV D,M DCX H MOV E,M ;DE = disk addr PUSH D LHLD FDE INX H MOV A,M ANI 3 MOV C,A ;unit MVI B,1 ;read cmd LXI D,FBUFF-1 DAD D ;internal buff addr XCHG POP H MVI A,1 ;1 sector CALL Dio RC ;error LHLD FDE LXI B,FDISKADD DAD B INR M INX H JNZ FRDB2 INR M ;bump disk addr FRDB2: INX H MOV A,M ORA A JNZ FRDB3 DCR M ;decrement sector count INX H FRDB3: DCR M XRA A ;accum = offset to next byte FRDBYT: LHLD FDE LXI B,FBUFF DAD B MOV C,A MVI B,0 DAD B MOV A,M ;get byte LHLD FMEM MOV M,A ;put in user memory INX H SHLD FMEM LHLD FXFER INX H SHLD FXFER LHLD FCNT DCX H SHLD FCNT LHLD FDE LXI B,FBYTEOFF DAD B INR M ;bump offset (0 means empty) FRDBX: STC CMC RET ; ;Read/write okay FXOK: LHLD FXFER ;get # bytes done RET FXFERR: LXI D,-1 ;error exit RET ; ;Transfer the arguments from the stack FXARGS: LXI H,4 DAD SP LXI D,FXALIST MVI C,6 FXALP: MOV A,M STAX D INX H INX D DCR C JNZ FXALP RET ; ; ;Write to a file ;Call: FWRITE(memaddr,bytes,unit) ; (see FREAD for explanation...they are same) ; FWRITE: CALL FXARGS LXI H,0 SHLD FXFER CALL FOPFDE JC FXFERR MOV A,M CPI 2 JNZ FXFERR ;Main writing loop FWRITE1: LHLD FCNT MOV A,H ORA L JZ FXOK ;done MOV A,H ORA A JNZ FWRITE3 ;less than 256 FWRITE2: CALL FWRTB ;write a byte JC FXFERR JMP FWRITE1 ;more than 256 means it goes direct to user FWRITE3: LHLD FDE LXI B,FBYTEOFF DAD B MOV A,M JNZ FWRITE2 ;empty internal buffer first LHLD FDE LXI B,FDISKADD DAD B MOV E,M INX H MOV D,M MOV A,E CMA MOV E,A MOV A,D CMA MOV D,A INX D ;-FDA LXI H,349 DAD D ;349-FDA = # sectors till end XCHG LDA FCNT+1 MOV L,A MVI H,0 ;make HL = # requested MOV A,H CMP D JNZ FWRITE4 MOV A,L CMP E FWRITE4: JC FWRITE5 XCHG ;can't do this many FWRITE5: MOV A,H ORA L JZ FXOK ;no room at all PUSH H MOV A,L PUSH PSW LHLD FDE INX H MOV A,M ANI 3 MOV C,A ;unit MVI B,0 ;write cmd LXI D,FDISKADD-1 DAD D MOV E,M INX H MOV D,M ;DE = FDA LHLD FMEM XCHG POP PSW CALL Dio POP D JC FXFERR ;good write LHLD FDE LXI B,FDISKADD DAD B MOV A,E ADD M MOV M,A INX H MOV A,D ADC M MOV M,A INX H MOV A,E ADD M MOV M,A INX H MOV A,D ADC M MOV M,A LHLD FMEM MOV B,E MVI C,0 ;make # bytes DAD B SHLD FMEM LHLD FXFER DAD B SHLD FXFER MOV A,B CMA MOV B,A MOV A,C CMA MOV C,A INX B LHLD FCNT DAD B SHLD FCNT LHLD FDE LXI B,FDISKADD DAD B MOV E,M INX H MOV D,M XCHG LXI D,350 MOV A,H CMP D JNZ FWRITE6 MOV A,L CMP E FWRITE6: JC FWRITE1 ;still room on disk JMP FXOK ;disk full, but no more, please ; ;Write a single byte from user memory ;carry set if error FWRTB: LHLD FDE LXI B,FBYTEOFF DAD B PUSH H MOV C,M INX H MVI B,0 DAD B ;index to place to put it XCHG LHLD FMEM MOV A,M STAX D ;copy to system buffer INX H SHLD FMEM LHLD FXFER INX H SHLD FXFER LHLD FCNT DCX H SHLD FCNT POP H INR M ;bump offset JZ FWRTB1 ;opps, filled buffer FWRTBX: STC CMC RET ;Need to write system buffer to disk FWRTB1: INX H PUSH H ;@buff LHLD FDE INX H MOV A,M ANI 3 MOV C,A ;unit MVI B,0 ;write cmd LXI D,FDISKADD-1 DAD D MOV A,M INX H MOV H,M MOV L,A ;get the disk addr POP D ;DE = mem addr, HL = disk addr MVI A,1 CALL Dio RC ;error LHLD FDE LXI B,FDISKADD DAD B INR M ;bump NDA INX H JNZ FWRTB3 INR M FWRTB3: INX H INR M ;& DNS INX H JNZ FWRTB4 INR M FWRTB4: INX H INX H ;HL = @ buff XRA A FWRTB5: MVI M,0 INX H INR A JNZ FWRTB5 ;clear buffer after every write LHLD FDE LXI B,FDISKADD DAD B MOV E,M INX H MOV D,M XCHG LXI D,350 MOV A,H CMP D JNZ FWRTB6 MOV A,L CMP E FWRTB6: JC FWRTBX ;still room LXI H,0 SHLD FCNT ;full...no more can be done LHLD FDE LXI B,FBYTEOFF DAD B MVI M,0 ;and declare buffer empty JMP FWRTBX ; ;File I/O storage area ;Following are the arguments FOPARGS: FILENAME: DS 2 ;Addr file name FNUMB: DS 2 ;Size on open (unused) FXALIST: FUNIT: DS 2 ;Unit # FCNT: FTYPE: DS 2 ;Direction of transfer FMEM: DS 2 ;Current memory address ;Start of local storage FDE: DS 2 ;Addr of current unit block FXFER: DS 2 ;# bytes done FFILE: DS 40 ;filename buffer FZERO: DS 1 ;known null word for closing ; ;Unit block formats: ; +0 = type of open (0 = free, 1 = read, 2 = write) ; +1 = Poly FDE block (max 44 bytes) ; +45 = FDA (also NDA) next disk addr for xfer ; +47 = DNS sector count (reads decrements, write inc's) ; +49 = offset to next byte in internal buffer ; +50 = internal buffer (256 bytes) FDEBUFF: DS FDESIZE * FDENUM ; ; DS 10 ;fudge factor ;small-c compiler rev 1.0 ;/* */ ;/* Patch to poly I/O routines */ ;/* */ ;#define NULL 0 ;#define eol 13 ;fopen(sname,mode) fopen: ; char *sname,*mode; ;{ int xfermode,unit; PUSH B PUSH B ; if(*mode=='w')xfermode=2; LXI H,6 DAD SP CALL ccgint CALL ccgchar PUSH H LXI H,119 POP D CALL cceq MOV A,H ORA L JZ cc10001 LXI H,2 DAD SP PUSH H LXI H,2 POP D CALL ccpint ; else xfermode=1; JMP cc10002 cc10001: LXI H,2 DAD SP PUSH H LXI H,1 POP D CALL ccpint cc10002: ; unit=0; LXI H,0 DAD SP PUSH H LXI H,0 POP D CALL ccpint ; while(unit<4) cc10003: LXI H,0 DAD SP CALL ccgint PUSH H LXI H,4 POP D CALL cclt MOV A,H ORA L JZ cc10004 ; if(FOPEN(xfermode,++unit,-1,sname)==0) LXI H,2 DAD SP CALL ccgint PUSH H LXI H,2 DAD SP PUSH H CALL ccgint INX H POP D CALL ccpint PUSH H LXI H,1 CALL ccneg PUSH H LXI H,14 DAD SP CALL ccgint PUSH H CALL FOPEN XCHG LXI H,8 DAD SP SPHL XCHG PUSH H LXI H,0 POP D CALL cceq MOV A,H ORA L JZ cc10005 ; return unit; LXI H,0 DAD SP CALL ccgint POP B POP B RET ; return NULL; cc10005: JMP cc10003 cc10004: LXI H,0 POP B POP B RET ; } ;fclose(unit) fclose: ; int unit; ;{ return FCLOSE(unit); LXI H,2 DAD SP CALL ccgint PUSH H CALL FCLOSE POP B RET ;} ;getc(unit) getc: ; int unit; ;{ char buff[1];int flag; DCX SP PUSH B ; flag=FREAD(buff,1,unit); LXI H,0 DAD SP PUSH H LXI H,4 DAD SP PUSH H LXI H,1 PUSH H LXI H,11 DAD SP CALL ccgint PUSH H CALL FREAD POP B POP B POP B POP D CALL ccpint ; if((flag==0)|(flag==-1))return -1; LXI H,0 DAD SP CALL ccgint PUSH H LXI H,0 POP D CALL cceq PUSH H LXI H,2 DAD SP CALL ccgint PUSH H LXI H,1 CALL ccneg POP D CALL cceq POP D CALL ccor MOV A,H ORA L JZ cc10006 LXI H,1 CALL ccneg INX SP POP B RET ; return(buff[0]&255); cc10006: LXI H,2 DAD SP PUSH H LXI H,0 POP D DAD D CALL ccgchar PUSH H LXI H,255 POP D CALL ccand INX SP POP B RET ; } ;putc(c,unit) putc: ; char c;int unit; ;{ char buff[1];int flag; DCX SP PUSH B ; buff[0]=c; LXI H,2 DAD SP PUSH H LXI H,0 POP D DAD D PUSH H LXI H,9 DAD SP CALL ccgchar POP D CALL ccpchar ; flag=FWRITE(buff,1,unit); LXI H,0 DAD SP PUSH H LXI H,4 DAD SP PUSH H LXI H,1 PUSH H LXI H,11 DAD SP CALL ccgint PUSH H CALL FWRITE POP B POP B POP B POP D CALL ccpint ; if((flag==0)|(flag==-1))return -1; LXI H,0 DAD SP CALL ccgint PUSH H LXI H,0 POP D CALL cceq PUSH H LXI H,2 DAD SP CALL ccgint PUSH H LXI H,1 CALL ccneg POP D CALL cceq POP D CALL ccor MOV A,H ORA L JZ cc10007 LXI H,1 CALL ccneg INX SP POP B RET ; else return(c&255); JMP cc10008 cc10007: LXI H,7 DAD SP CALL ccgchar PUSH H LXI H,255 POP D CALL ccand INX SP POP B RET cc10008: ; } INX SP POP B RET ;gets(buff) gets: ; char buff[]; ;{ ; int k; PUSH B ; k=0; LXI H,0 DAD SP PUSH H LXI H,0 POP D CALL ccpint ; while((buff[k]=INCH())!=eol) cc10009: LXI H,4 DAD SP CALL ccgint PUSH H LXI H,2 DAD SP CALL ccgint POP D DAD D PUSH H CALL INCH POP D CALL ccpchar PUSH H LXI H,13 POP D CALL ccne MOV A,H ORA L JZ cc10010 ; { ; if(buff[k]==24){k=0;putchar(24);} LXI H,4 DAD SP CALL ccgint PUSH H LXI H,2 DAD SP CALL ccgint POP D DAD D CALL ccgchar PUSH H LXI H,24 POP D CALL cceq MOV A,H ORA L JZ cc10011 LXI H,0 DAD SP PUSH H LXI H,0 POP D CALL ccpint LXI H,24 PUSH H CALL putchar POP B ; else if(buff[k]==127) JMP cc10012 cc10011: LXI H,4 DAD SP CALL ccgint PUSH H LXI H,2 DAD SP CALL ccgint POP D DAD D CALL ccgchar PUSH H LXI H,127 POP D CALL cceq MOV A,H ORA L JZ cc10013 ; {if(k>0) LXI H,0 DAD SP CALL ccgint PUSH H LXI H,0 POP D CALL ccgt MOV A,H ORA L JZ cc10014 ; {k=k-1; LXI H,0 DAD SP PUSH H LXI H,2 DAD SP CALL ccgint PUSH H LXI H,1 POP D CALL ccsub POP D CALL ccpint ; putchar(127); LXI H,127 PUSH H CALL putchar POP B ; } ; } cc10014: ; else JMP cc10015 cc10013: ; { ; putchar(buff[k]); LXI H,4 DAD SP CALL ccgint PUSH H LXI H,2 DAD SP CALL ccgint POP D DAD D CALL ccgchar PUSH H CALL putchar POP B ; k=k+1; LXI H,0 DAD SP PUSH H LXI H,2 DAD SP CALL ccgint PUSH H LXI H,1 POP D DAD D POP D CALL ccpint ; } cc10015: cc10012: ; } JMP cc10009 cc10010: ; buff[k]=0; LXI H,4 DAD SP CALL ccgint PUSH H LXI H,2 DAD SP CALL ccgint POP D DAD D PUSH H LXI H,0 POP D CALL ccpchar ; putchar(eol); LXI H,13 PUSH H CALL putchar POP B ; return buff; LXI H,4 DAD SP CALL ccgint POP B RET ;} ;getchar() getchar: ;{ ; return(putchar(INCH())); CALL INCH PUSH H CALL putchar POP B RET ;} ;putchar(c) putchar: ; char c; ;{ ; return(OUTCH(c)); LXI H,2 DAD SP CALL ccgchar PUSH H CALL OUTCH POP B RET ;} ;0 errors in compilation.