home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
simtel
/
sigm
/
vols000
/
vol010
/
als8cpm.asm
< prev
next >
Wrap
Assembly Source File
|
1984-04-29
|
17KB
|
612 lines
;**************************************************
;* *
;* ALS8CPM.ASM *
;* *
;* PROGRAM FOR CONVERTING PROCESSOR TECHNOLOGY *
;* ALS-8/SPKG-1 ASSEMBLER FILES TO CP/M FORMAT *
;* *
;* (C) COPYRIGHT 1980 *
;* ED ELIZONDO 6 CYPRESS CT EAST WINDSOR NJ 08520 *
;* A L L R I G H T S R E S E R V E D *
;* *
;* THIS PROGRAM MAY BE USED FREELY BY COMPUTER *
;* HOBBYISTS FOR NON-COMMERCIAL APPLICATIONS. *
;* IT MAY NOT BE USED FOR COMMERCIAL APPLICATIONS *
;* OR SOLD WITHOUT WRITTEN PERMISSION OF THE *
;* AUTHOR. *
;* *
;* REV 1.6 31 JAN 1980 *
;* *
;**************************************************
;
; NOTE: This program processes assembly language files
; prepared for the Processor Technology ALS-8 or Software
; Package No 1 assemblers to a format compatible with
; the CP/M ASM assembler. It requires the presence of
; CUTER/SOLOS or some other means of loading the ALS-8
; source file onto memory so that it can be saved by CP/M.
; It does not require the presence of anything other than
; CP/M during the remaining operations.
;
; The translation process operates in accordance with
; the following algorithms:
; Each line is converted independently. The line byte count
; and line number fields are deleted from the source lines
; and each line is terminated with a CR/LF sequence.
; A semicolon is placed ahead of all comment lines (for
; compatibility with MAC) and ahead of all comment fields.
; Leading spaces are deleted from comment fields only.
; Comment lines and the remainder of comment fields are
; passed unchanged, except for deletion of any exclamation
; marks.
; Periods used as dummy operands for formatting purposes
; are removed, as well as any leading spaces appearing in
; instructiona and operand fields. Operands enclosed in
; single quotes are passed unchanged.
; ASC pseudo-operators are changed to DB and the corresponding
; delimiters changed to single quotes.
; The '>' pseudo-operator is converted to an 'AND 0FFH' post
; operator and the '<' is similarly converted to a 'SHR 8'.
; Instruction, operand and comment fields are tabbed
; and colons are added to labels to "pretty" the output.
; The program utilizes slightly modified versions of the
; CP/M User's Group LIOS.ASM disk I/O routines (CPMUG 1.19)
;
; TO USE: 1) load your ALS-8 format program into RAM at 100H
; (If using SOLOS/CUTER, note the first two digits
; of program size returned by the load message.
; Convert to decimal and add 1 to obtain the
; number nn required in step 3).
; 2) boot up CP/M
; 3) type SAVE nn NAME1.EXT (where nn is number of
; pages of program size in decimal)
; 4) run the conversion program by typing:
; ALS8CPM NAME1.EXT NAME2.ASM
; where NAME2.ASM is the desired name of the CP/M
; compatible output file (note spaces between
; the above name fields)
; 5) edit the resulting ASM file to add the appropriate
; ORG statement.
; 6) assemble to locate any residual unique errors.
;
;*************************************************************
;
; BDOS ADDRESSES:
;
BDOS: EQU 0005 ;BDOS ENTRY POINT
SOURCE: EQU 5CH ;SOURCE FILE FCB
TBUF: EQU 0080H ;TRANSFER BUFFER
;
; BDOS FUNCTION CODES:
;
PRINT: EQU 9
OPEN: EQU 15
CLOSE: EQU 16
MAKE: EQU 22
READ: EQU 20
WRITE: EQU 21
DELETE: EQU 19
;
; ASCII CODES:
;
SPACE: EQU 20H
QUOTE: EQU 27H
TAB: EQU 09H
CR: EQU 0DH
LF: EQU 0AH
;
;***************************
;* MAIN PROGRAM *
;***************************
;
ORG 100H
;
LXI H,0 ;GET OLD STACK POINTER
DAD SP
SHLD OLDSTK ;SAVE IT FOR EXIT
LXI SP,NEWSTK ;SET UP NEW STACK
;
LXI D,MSSG0 ;SAY HELLO
CALL MESSAGE
;
CALL GETNAMES ;GET FILE NAMES FROM COMMAND LINE
CALL OPENFILES ;OPEN FILES FOR ACCESS
LXI D,MSSG8 ;WE'RE DOING FINE
CALL MESSAGE
;
CALL PROCESS ;PROCESS LINE BY LINE
CALL WEOF ;FILL LAST INCOMPLETE PAGE
;
ABEND: CALL CLOSEFILE ;CLOSE FILES
LXI D,MSSG9 ;WE'RE FINISHED
CALL MESSAGE
;
FIN: LHLD OLDSTK ;RESTORE OLD STACK POINTER
SPHL
RET ;RETURN TO CP/M
;
;
;****************************************
; G E T N A M E S *
; SUBROUTINE TO CHECK & GET FILE NAMES *
;****************************************
;
GETNAMES:
LDA SOURCE+1 ;FIRST CHAR OF SOURCE NAME
CPI SPACE ;EMPTY?
JZ ERROR6 ;YES, ERROR
LDA SOURCE+17 ;FIRST CHAR OF DEST NAME
CPI SPACE ;EMPTY?
JZ ERROR7 ;YES, ERROR
; MOVE DEST FCB TO SAFE PLACE
LXI D,SOURCE+16 ;START OF TEMP DEST FCB
LXI H,DEST ;WORKING DEST FCB
MVI B,16 ;NUMBER OF FCB CHARACTERS
CALL MOVE ;MOVE NAME
;
; INITIALIZE FCB'S
XRA A ;GET A 0
STA SOURCE+32 ;ZERO SOURCE NR FIELD
STA DEST+32 ;ZERO DEST NR FIELD
RET
;
;****************************************
; O P E N F I L E S *
; SUBROUTINE TO OPEN FILES FOR ACCESS *
;****************************************
;
OPENFILES:
MVI C,OPEN ;GET OPEN FUNCTION
LXI D,SOURCE
CALL BDOS ;OPEN SOURCE FILE
CPI 0FFH ;OPEN ERROR?
JZ ERROR1 ;YES, ABORT
;
MVI C,DELETE ;DELETE FUNCTION
LXI D,DEST
CALL BDOS ;DELETE EXISTING DEST FILE
MVI C,MAKE ;MAKE FUNCTION
LXI D,DEST
CALL BDOS ;CREATE NEW DEST FILE
CPI 0FFH ;MAKE ERROR?
JZ ERROR3 ;YES, ABORT
MVI C,OPEN ;OPEN FUNCTION
LXI D,DEST
CALL BDOS ;OPEN DEST FILE
RET
;
;***********************************
; P R O C E S S *
; ROUTINE TO PROCESS EACH LINE *
;***********************************
PROCESS:
XRA A ;CLEAR STRING FLAG
STA FLAG
CALL GETBYT ;GET LINE CHAR COUNT
CPI 1 ;END OF FILE?
JZ EOFMARK ;YES, PROCESS IT
DCR A ;UPDATE CHAR LINE COUNT
STA EOLCNT ;SAVE IT
MVI B,5 ;FIELD COUNT
LNUM: PUSH B ;MOVE PAST LINE NUMBER FIELD
CALL GETBYT ;READ A BYTE
POP B
CALL COUNT ;DECREMENT LINE COUNT
JZ PREMEND ;PREMATURE END OF LINE
DCR B ;DECREMENT FIELD COUNT
JNZ LNUM ;UNTIL DONE
;
LABEL: CALL GETBYT ;PROCESS LABEL FIELD
CPI '*' ;COMMENT LINE?
JZ COMLINE ;YES, PROCESS IT
CPI SPACE ;MISSING LABEL?
JZ INSTR ;THEN PROCESS INST
LABEL1: CALL OUTBYT ;OUTPUT LABEL CHAR
CALL COUNT ;DECREMENT LINE COUNT
JZ EOLINE ;IF END OF LINE
CALL GETBYT ;GET NEXT BYTE
CPI SPACE ;END OF ALS-8 LABEL?
JZ LABEL2 ;YES, EXIT LOOP
CPI ':' ;END OF INTEL LABEL?
JNZ LABEL1 ;NO, KEEP GOING
LABEL2: MVI A,':' ;YES, OUTPUT A COLON
CALL OUTBYT ;AND DROP THRU
INSTR: MVI A,TAB ;PROCESS INSTR FIELD
CALL OUTBYT ;TAB TO NEXT COLUMN
CALL DELSP ;DELETE LEADING SPACES
JC EOLINE ;IF END OF LINE
; CHECK FOR ASC PSEUDO-OP
CPI 'A' ;POSSIBLE ASC PSEUDO OP?
JNZ INSTR2 ;NO WAY
CALL COUNT ;DECREMENT LINE COUNT
JZ EOLINE ;IF END OF LINE
CALL GETBYT ;GET NEXT BYTE
CPI 'S' ;ASC PSEUDO OP?
JNZ RECOV2 ;NO, RECOVER LAST TWO BYTES
CALL COUNT ;DECREMENT LINE COUNT
JZ EOLINE ;IF END OF LINE
CALL GETBYT ;GET NEXT BYTE
CPI 'C' ;ASC PSEUDO OP?
JNZ RECOV3 ;NO, RECOVER LAST 3 BYTES
;
; CONVERT ASC PSEUDO OP TO DB
LXI D,DBOP ;OUTPUT A 'DB'
CALL PUTSTRING
MVI A,TAB ;END OF INSTR FIELD
CALL OUTBYT ;TAB TO NEXT COLUMN
;
; HANDLE ASC OPERAND AND CONVERT DELIMITERS
CALL DELSP ;DELETE EXTRA SPACES
JC EOLINE ;IF END OF LINE
STA DELIM ;SAVE THE ASC DELIMITER
MVI A,QUOTE ;GET CPM DELIMITER
ASC2: CALL OUTBYT ;OUTPUT IT
CALL COUNT ;DECREMENT LINE COUNT
JZ EOLINE ;IF END OF LINE
LDA DELIM ;GET DELIMITER
MOV B,A ;INTO B
PUSH B ;SAVE B
CALL GETBYT ;GET NEXT BYTE
POP B ;RESTORE B
CMP B ;DELIMITER?
JNZ ASC2 ;NO, KEEP GOING
MVI A,QUOTE ;YES, GET CPM DELIMITER
CALL OUTBYT ;OUTPUT IT
JMP COMMENT ;REMAINDER MUST BE COMMENT
;
; RECOVER LAST TWO BYTES (NOT ASC PSEUDO OP)
RECOV2: STA TEMP2 ;SAVE LAST BYTE
MVI A,'A' ;FIRST BYTE WAS AN 'A'
CALL OUTBYT ;OUTPUT IT
LDA TEMP2 ;GET LAST BYTE
JMP INSTR2 ;CONTINUE NORMALLY
;
; RECOVER LAST 3 BYTES (NOT ASC PSEUDO OP)
RECOV3: STA TEMP2 ;SAVE LAST BYTE
LXI D,ASOP ;WE KNOW LAST 2 BYTES WERE 'AS'
CALL PUTSTRING ;SO OUTPUT THEM
LDA TEMP2 ;GET LAST BYTE
;
; HANDLE REMAINDER OF INSTRUCTION FIELD
INSTR2: CALL PASS ;OUTPUT REST OF FIELD
JC EOLINE ;IF END OF LINE
;
OPERAND:
MVI A,TAB ;PROCESS OPERAND FIELD
CALL OUTBYT ;TAB TO NEXT COLUMN
CALL DELSP ;DELETE LEADING SPACES
JC EOLINE ;IF END OF LINE
;
; CHECK FOR '<' SPECIAL OPERATOR
OPER1: CPI '<' ;LEFT BYTE MASK?
JNZ OPER3 ;NO WAY
CALL COUNT ;DECREMENT END OF LINE COUNT
JZ EOLINE ;IF END OF LINE
CALL GETBYT ;GET NEXT BYTE
CALL PASS ;OUTPUT REST OF FIELD
JC EOLINE ;IF PREMATURE END OF LINE
LXI D,LBYTE ;OUTPUT A SHIFT RIGHT EXPR
CALL PUTSTRING
JMP COMMENT ;REMAINDER MUST BE COMMENT
;
; CHECK FOR '>' SPECIAL OPERATOR
OPER2: CPI '>' ;RIGHT BYTE MASK?
JNZ OPER3 ;NO WAY
CALL COUNT ;DECREMENT LINE COUNT
JZ EOLINE ;IF END OF LINE
CALL GETBYT ;GET NEXT BYTE
CALL PASS ;OUTPUT REST OF FIELD
JC EOLINE ;IF END OF LINE
LXI D,RBYTE ;THEN A MASK RIGHT EXP
CALL PUTSTRING
JMP COMMENT ;REMAINDER MUST BE COMMENT
; HANDLE REMAINDER OF OPERAND
OPER3: CPI QUOTE ;IS IT A QUOTE?
CZ TOGGLE ;YES, TOGGLE STRING FLAG
CPI '.' ;IS IT A PERIOD?
JZ STRING ;YES, CHECK IF PART OF STRING
CPI SPACE ;IS IT A SPACE?
JNZ OPER4 ;NO, PROCESS IT
STRING: STA TEMP ;SAVE BYTE
LDA FLAG ;IS CHAR WITHIN STRING?
ORA A
JZ COMMENT ;NO, END OF OPERAND FIELD
LDA TEMP ;YES, GET BACK BYTE
OPER4: CALL OUTBYT ;OUTPUT BYTE
CALL COUNT ;DECREMENT LINE COUNT
JZ EOLINE ;IF END OF LINE
CALL GETBYT ;GET NEXT BYTE
JMP OPER3 ;KEEP GOING
;
;
COMLINE: ;PROCESS COMMENT LINE
MVI A,';' ;GET A SEMICOLON
JMP CLOOP ;OUTPUT IT & REST OF LINE
COMMENT: ;PROCESS COMMENT FIELD
MVI A,TAB
CALL OUTBYT ;TAB TO NEXT COLUMN
MVI A,';' ;GET A SEMICOLON
CALL OUTBYT ;OUTPUT IT
CALL DELSP ;DELETE LEADING SPACES
JC EOLINE ;IF END OF LINE
CPI '!' ;EXCLAMATION MARK?
JZ CLOOP2 ;YES, DELETE IT
CLOOP: CALL OUTBYT ;NO, OUTPUT IT
CLOOP2: CALL COUNT ;DECREMENT LINE COUNT
JZ EOLINE ;IF END OF LINE
CALL GETBYT ;GET NEXT BYTE
CPI '!' ;EXCLAMATION MARK?
JZ CLOOP2 ;YES, DELETE IT
JMP CLOOP ;KEEP GOING
PREMEND: ;PREMATURE END OF LINE
MVI A,CR ;OUTPUT A CARRIAGE RET
CALL OUTBYT
EOLINE: MVI A,LF ;NORMAL END OF LINE
CALL OUTBYT ;OUTPUT A LINE FEED
JMP PROCESS ;PROCESS NEXT LINE
;
EOFMARK:
MVI A,'Z'-40H ;GET A CPM EOF MARK
CALL OUTBYT ;OUTPUT IT
RET ;EXIT PROCESS
;
;
TOGGLE: PUSH PSW ;FLAG SET IF STRING IN QUOTES
LDA FLAG ;TOGGLE FLAG
CMA
STA FLAG ;THAT'S ALL
POP PSW
RET
;
; DELETE EXTRA SPACES
DELSP: CALL COUNT ;DECREMENT LINE COUNT
JZ DELSP2 ;IF PREMATURE END OF LINE
CALL GETBYT ;GET NEXT BYTE
CPI SPACE ;SPACE?
JZ DELSP ;YES, DELETE IT
ORA A ;RESET CARRY FLAG
RET ;RETURN WITH BYTE
DELSP2: STC ;SET CARRY FLAG FOR EOL
RET ;RETURN WITH FLAG SET
;
; OUTPUT BYTES UNTIL END OF FIELD
PASS: CALL OUTBYT ;OUTPUT BYTE
CALL COUNT ;DECREMENT LINE COUNT
JZ PASS2 ;IF PREMATURE END OF LINE
CALL GETBYT ;GET NEXT BYTE
CPI SPACE ;END OF FIELD?
JNZ PASS ;NO, KEEP GOING
ORA A ;RESET CARRY FLAG
RET ;RETURN WITH SPACE
PASS2: STC ;SET CARRY FLAG FOR EOL
RET ;RETURN WITH FLAG SET
;
COUNT: LDA EOLCNT ;DECREMENT END OF LINE COUNT
DCR A
STA EOLCNT ;THAT'S ALL
RET
;
;*************************************
; P U T S T R I N G *
; ROUTINE TO OUTPUT A STRING TO DISC *
;*************************************
;
PUTSTRING:
LDAX D ;GET A BYTE
CPI '$' ;TERMINATOR?
RZ ;YES, RETURN
PUSH D ;SAVE D&E
CALL OUTBYT ;NO, OUTPUT BYTE
POP D ;RESTORE D&E
INX D ;BUMP POINTER
JMP PUTSTRING ;KEEP GOING
;
;********************
; CANNED STRINGS: *
;********************
;
ASOP: DB 'AS$' ;STRING TO RECOVER AS STRING
DBOP: DB 'DB$' ;STRING TO REPLACE ASC OP
RBYTE: DB ' AND 0FFH$' ;STRING TO REPLACE ">" OP
LBYTE: DB ' SHR 8$' ;STRING TO REPLACE "<" OP
;*********************************
; O U T B Y T *
; ROUTINE TO OUTPUT A BYTE *
; *
; INPUT: A=BYTE *
;*********************************
OUTBYT: STA TEMP ;SAVE BYTE
OUT1: LXI H,OBUF+128
XCHG ;BUFFER END ADDR IN DE
LHLD OUTPT ;CURRENT ADDR IN HL
CALL CPHL ;TEST FOR END OF BUFFER
JZ OUT2 ;YES, WRITE
LDA TEMP
MOV M,A ;STORE DATA BYTE IN BUFFER
INX H ;BUMP BUFFER POINTER
SHLD OUTPT ;SAVE BUFFER POINTER
ORA A
RET ;EXIT
OUT2: LXI D,OBUF ;POINT TO OUTPUT BUFFER
LXI H,TBUF ;TEMP BUFFER
MVI B,128
CALL MOVE ;COPY BUFFERS
MVI C,WRITE ;WRITE FUNCTION
LXI D,DEST ;OUTPUT FCB
CALL BDOS ;ISSUE WRITE
CPI 0FFH
JZ ERROR3
CPI 2
JZ ERROR4
CPI 1
JZ ERROR5
LXI H,OBUF ;RESET POINTER
SHLD OUTPT
JMP OUT1 ;CONTINUE
;*********************************
; G E T B Y T *
; ROUTINE TO READ A BYTE *
; *
; OUTPUT: A=BYTE *
;*********************************
GETBYT: LXI H,IBUF+128
XCHG ;BUFFER END ADDR. IN DE
LHLD INPTR ;CURRENT POINTER IN HL
CALL CPHL ;TEST FOR END OF BUFFER
JZ GETB2 ;YES, READ
GETB1: MOV A,M ;GET BYTE
INX H ;BUMP POINTER
SHLD INPTR ;SAVE POINTER
ORA A ;RESET CARRY
RET
GETB2: MVI C,READ ;READ FUNCTION
LXI D,SOURCE ;FCB ADDRESS
CALL BDOS ;ISSUE READ
CPI 0 ;ERROR?
JNZ ERROR2 ;YES
LXI D,TBUF ;POINT TO TEMP BUFFER
LXI H,IBUF ;INPUT BUFFER
MVI B,128
CALL MOVE ;COPY BUFFER
LXI H,IBUF ;RESET BUFFER POINTER
SHLD INPTR
JMP GETB1 ;CONTINUE
;***********************************
; M O V E *
; ROUTINE TO MOVE BLOCKS OF DATA *
;***********************************
MOVE: LDAX D ;GET BYTE
MOV M,A ;STORE BYTE
INX H
INX D ;BUMP POINTERS
DCR B ;DECREMENT COUNT
JNZ MOVE ;LOOP
RET
;*********************************
; C P H L *
; ROUTINE TO COMPARE HL VS DE *
;*********************************
CPHL: MOV A,H
CMP D
RNZ
MOV A,L
CMP E
RET
;**********************************
; W E O F *
; ROUTINE TO FILL UP LAST RECORD *
; WITH CP/M EOF MARKS *
;**********************************
WEOF: LXI H,OBUF+128 ;END OF BUFFER
XCHG
LHLD OUTPT ;WHERE WE ARE
CALL CPHL ;SAME?
JZ OUTBYT ;YES, WRITE LAST RECORD
MVI A,'Z'-40H ;NO, GET A CPM EOF MARK
CALL OUTBYT ;OUTPUT IT TO BUFFER
JMP WEOF ;KEEP GOING
;
;********************************
; C L O S E F I L E *
; SUBROUTINE TO CLOSE FILES *
;********************************
;
CLOSEFILE:
MVI C,CLOSE ;CLOSE FUNCTION
LXI D,DEST
CALL BDOS ;CLOSE DESTINATION FILE
MVI C,CLOSE ;CLOSE FUNCTION
LXI D,SOURCE
CALL BDOS ;CLOSE SOURCE FILE
RET
;
;
;*****************************
; ERROR HANDLERS *
;*****************************
;
ERROR1: LXI D,MSSG1
JMP ERRMSG
ERROR2: LXI D,MSSG2
JMP ABORT
ERROR3: LXI D,MSSG3
JMP ERRMSG
ERROR4: LXI D,MSSG4
JMP ABORT
ERROR5: LXI D,MSSG5
JMP ABORT
ERROR6: LXI D,MSSG6
JMP ERRMSG
ERROR7: LXI D,MSSG7
ERRMSG: CALL MESSAGE
JMP FIN ;RETURN TO CPM
ABORT: CALL MESSAGE
JMP ABEND ;CLOSE FILES & RETURN TO CPM
;
;*********************************
; M E S S A G E *
; SUBROUTINE TO OUTPUT MESSAGE *
;*********************************
;
MESSAGE:
MVI C,PRINT ;PRINT FUNCTION
CALL BDOS
RET
;
;***************************
; MESSAGES: *
;***************************
;
MSSG0 DB 'ALS-8 to CP/M File Converter - ver 1.6',CR,LF
DB 'by Ed Elizondo',CR,LF,'$'
MSSG1 DB 'Source file not on disk',CR,LF,'$'
MSSG2 DB 'Read past end of file',CR,LF,'$'
MSSG3 DB 'Directory full',CR,LF,'$'
MSSG4 DB 'Disk full',CR,LF,'$'
MSSG5 DB 'Error in extending file',CR,LF,'$'
MSSG6 DB 'No source file indicated',CR,LF,'$'
MSSG7 DB 'No destination file indicated',CR,LF,'$'
MSSG8 DB 'Converting file',CR,LF,'$'
MSSG9 DB 'Done',CR,LF,'$'
;*************************
; DATA BUFFERS: *
;*************************
;
TEMP: DS 1 ;TEMPORARY SAVE BYTE
TEMP2: DS 1 ;ANOTHER ONE
DELIM DS 1 ;ASC DELIMITER SAVE BYTE
FLAG: DB 0 ;SWITCH FOR QUOTED STRINGS
EOLCNT: DB 0 ;END OF LINE COUNT
DEST: DS 33 ;DEST FILE FCB
;
OUTPT: DW OBUF ;OUTPUT POINTER
INPTR: DW IBUF+128 ;INPUT POINTER
IBUF: DS 128 ;INPUT BUFFER
OBUF: DS 128 ;OUTPUT BUFFER
;
OLDSTK: DS 2 ;OLD STACK POINTER
DS 40H ;STACK AREA
NEWSTK: EQU $
;
END