.title binten.mac ;convert signed 16-bit binary data to decimal ASCII ;Copyright John Comeau, Industrial Control Technology, 1996 ;Use of and modifications to this program are granted according to GNU license. ;This was written specifically for use by wpalmer@oasys.dt.navy.mil. .ident /x01.00/ ;experimental version ;Note: messaging routines don't work on RSX11M V4.1 due to bug in TKB! ; The callsym prt,msgnum statements generate CALL 0! ;debug=1 ;comment out when debugged cr=13. lf=10. ;comment out RSX for an RT11 system rsx=1 .iif df debug, .list me,meb ;show macro expansions .iif ndf rsx, rt11=1 .iif df rt11, errbyt=52 ;define location of system status byte .enable mcl ;let MAC do the hard work .macro push arg mov arg,-(sp) .endm push ; .macro pop arg mov (sp)+,arg .endm pop ; .macro symbol text,number ;make a unique symbol with letters+# text'number: .endm symbol ; .macro getsym text,number,dest ;get symbol into destination mov #text'number,dest .endm getsym ; .macro callsym text,number ;make call instruction from symbol call text'number .endm callsym ; .macro message string .iif ndf msgnum, msgnum=0 .save ;current program section .pdata data ;switch to pure data section msgnum=msgnum+1 ;update the message number symbol msg,\msgnum .asciz |string| .even ;so any word data following is aligned properly .restore ;back to previous psect .endm message ; .macro print string,p1,p2,p3,p4,p5,p6,p7,p8,p9 .if df rsx ;only useful as is under RSX11M message <%2R -- string> c=0 ;arg count callsym prt,\msgnum ;routine created to print specific message .save ;current psect .pcode print ;separate code section for messaging symbol prt,\msgnum ;create symbol for calling here ror -(sp) ;save carry flag on stack push r2 ;save working registers push r1 push r0 push $dsw ;save status word .irp arg, .if nb arg push arg ;push any parameters c=c+1 ;inc arg count .endc ;nb arg .endr push tskbuf+2 ;taskname in radix-50 push tskbuf mov sp,r2 ;save parameter list location getsym msg,\msgnum,r1 ;point to the string add #-132.,sp ;output buffer, hopefully large enough... mov sp,r0 ;address of output buffer on stack call $edmsg ;format the text mov sp,r0 ;restore address munged by EDMSG .iif ndf qioefn, qioefn=1 .iif ndf tiodev, tiodev=5 qiow$s #io.wvb,#tiodev,#qioefn,,,, add #132.,sp ;clean buffer off stack add #+4,sp ;and parameters/taskname pop $dsw ;restore status word, registers, and flag pop r0 pop r1 pop r2 rol (sp)+ return .restore .endc ;rsx .endm print ; .macro dbgmsg string,p1,p2,p3,p4,p5,p6,p7,p8,p9 .iif df debug, print ,p1,p2,p3,p4,p5,p6,p7,p8,p9 .endm dbgmsg ;print message only if DEBUG is defined ; .iif df rsx, .pcode code ;establish program segments if RSX11M .enable lsb ;local symbol block despite psect switching main: .if df rt11 mov sp,r5 ;save stack pointer .csigen #buffer,#defext ;parse input line to get file args mov r5,sp ;clean returned options off stack .iff ;RSX usage .idata impure tskbuf: .blkw 16. ;buffer for GTSK$ data .pcode code gtsk$s #tskbuf dbgmsg gcml$ #cmdblk,#prompt,#prlen ;get the command line call 10$ ;check for error csi$1 #csiblk,cmdblk+g.cmld+2,cmdblk+g.cmld ;initial parse call 20$ ;check for error csi$2 r0,output ;parse output filespec call 30$ ;check for error dbgmsg ,c.devd(r0),c.devd+2(r0) open$w #outfdb,,#csiblk+c.dsds ;open the output call 40$ ;trap any error csi$2 #csiblk,input ;parse input filespec call 50$ ;error check open$r #inpfdb,,#csiblk+c.dsds ;open the input file call 60$ ;quit on error mov f.efbk(r0),inefbk ;store end-of-file block number... mov f.efbk+2(r0),inefbk+2 ;... mov f.ffby(r0),inffby ;and size of final block add #1,inefbk+2 ;point one past the end adc inefbk ;... .iftf ;either RSX or RT call convert ;signed 16-bit binary to decimal ASCII call 70$ ;quit on error .iff ;RSX usage close$ #outfdb ;now close the output file call 80$ ;abort on error exst$s #ex$suc .ift ;RT11 usage .close #0 .exit .iftf 10$: ;user-friendly error messages go here... 20$: 30$: 40$: 50$: 60$: 70$: 80$: bcc 99$ .iff exst$s #ex$err .ift .exit ;rt11 exit call .iftf 99$: return .endc ;RT11 .dsable lsb convert: .enable lsb mov #numbuf,r4 ;point to number conversion buffer 10$: .if df rsx dbgmsg read$ #inpfdb ;get the next block call 100$ ;check on error or done wait$ r0 ;always necessary with block I/O call 100$ ;check on error mov #inbuf,r5 ;point to input... mov #256.,r3 ;number of words to convert cmp f.bkvb(r0),inefbk ;are we on the last block?... bne 20$ ;skip if not cmp f.bkvb+2(r0),inefbk+2 ;... bne 20$ tst inffby ;see if size specified beq 20$ ;skip if not mov inffby,r3 ;use specified size of final block asr r3 ;now make a word count .iff ;RT11 read routine goes here... .readw #rdlist,#3 call 100$ inc rdlist ;bump block number for next READ .endc ;rsx 20$: call binten ;do the conversion... movb #cr,(r4)+ ;store CRLF movb #lf,(r4)+ cmp r4,#numbuf+512. ;at end of block? call 110$ ;if so, store it sob r3,20$ ;loop till this block is done jmp 10$ ;then get another block until EOF ; 100$: bcc 109$ ;continue if no error .if df rsx ;finished program will check for various errors, we'll assume EOF close$ #inpfdb .iff ;rsx (rt11) .close #3 .iftf ;either/or tst (sp)+ ;don't continue cmp r4,#numbuf ;has pointer moved from start? beq 109$ ;just exit if not .iff ;RT11 only uses ^Z as EOF marker with text files movb #26.,(r4)+ ;else mark with control-Z .ift sub #numbuf,r4 ;get byte count write$ #outfdb,#numbuf,r4 ;flush to disk wait$ r0 mov r4,f.ffby(r0) ;set end-of-file before closing sub #1,f.bkvb+2(r0) ;but also must set back final block sbc f.bkvb(r0) ;... mov f.bkvb(r0),f.efbk(r0) ;... mov f.bkvb+2(r0),f.efbk+2(r0) ;... .iff ;rsx (RT11) .writw #wrtlst,#0 .iftf 109$: return ; 110$: blo 119$ ;loop back if the block is not yet overfilled .ift ;RSX11M write$ #outfdb ;flush to output wait$ r0 .iff .writw #wrtlst,#0 inc wrtblk .endc mov #numbuf+512.,r2 ;point to overflow mov #numbuf,r1 ;destination sub r2,r4 ;make count to move beq 116$ ;skip if nothing 112$: movb (r2)+,(r1)+ ;store the extra characters sob r4,112$ ;loop till done 116$: mov r1,r4 ;reset R4 to start of buffer... 119$: return .dsable lsb ; ;This procedure actually converts the word into its decimal representation binten: .enable lsb jsr r0,savr03 ;save first 4 registers mov #tentbl,r2 ;point to conversion table clr r1 ;OR value to make ASCII digit; initially null clr r3 ;counter of subtractions for each digit value dbgmsg ,(r5) mov (r5)+,r0 ;get next digit from global pointer bpl 10$ ;skip if positive movb #'-,(r4)+ ;else store minus sign in output neg r0 ;then make it positive 10$: inc r3 ;bump the counter sub (r2),r0 ;subtract until it goes negative bpl 10$ ;loop until negative add (r2),r0 ;then undo the damage dec r3 ;... bne 20$ ;store it if nonzero tst r1 ;zeroes enabled? beq 30$ ;skip if not 20$: movb #'0,r1 ;enable ASCII conversion bisb r1,r3 ;make digit ASCII movb r3,(r4)+ ;then store the digit clr r3 ;prepare register for another round 30$: tst (r2)+ ;advance to next table entry tst (r2) ;see if end bne 10$ ;loop if not done bisb #'0,r0 ;else show ones digit movb r0,(r4)+ ;store it... return ;done this number, let main program insert end-of-record tentbl: .word 10000.,1000.,100.,10.,0 .dsable lsb ; savr03: push r1 ;save registers 1 thru 3, r0 already on stack push r2 ;... push r3 ;... call (r0) ;now continue in subroutine... pop r3 ;on exit, restore registers and return to caller pop r2 ;... pop r1 ;... pop r0 ;... return ; .if df rsx cmdblk: gcmlb$ 1,,,5 ;#levels,,,LUN prompt: .ascii "BINTEN>" prlen=.-prompt .even csi$ ;define control block offset .even ;docs say this is necessary csiblk: .blkb c.size ;set up control block .even ;just in case fsrsz$ 4 ;buffers for GCML$ file, input, and output inpfdb: fdbdf$ ;define input FDB fdop$a 1,,definp,fo.rd!fa.shr ;LUN 1, shared read fdrc$a fd.rwm ;allow block I/O fdbk$a inbuf,512. ;buffer location and size outfdb: fdbdf$ ;define output FDB fdop$a 2,,defout ;LUN 2 fdrc$a fd.rwm ;block I/O fdbk$a numbuf,512. ;buffer location, size definp: nmblk$ SPECTRUM,DAT,,SY,0 ;default input filespec defout: nmblk$ SPECTRUM,TXT,,SY,0 ;default output specification .idata impure inefbk: .blkw 2 ;end of file block for input file inffby: .blkw 1 ;first free byte (size of final block) inbuf: .blkw 256. ;one block's worth numbuf: .blkw 260. ;can overflow by as much as 8 bytes: -32768 .iff ;rsx (rt11) rdlist: .word 0,0,inbuf,256.,0 wrtlst: .word 0,0,numbuf,256.,0 defext: .rad50 /DAT/ /TXT/ / / / / buffer=. .endc ;rsx .end main