N>SET BURST1 N ; DYN>SET BURST2 N ; DYN>SET BURST3 N ; DYN>KILL .mcall gtsk$s ,qiow$s ,exit$s ,exst$s STRING = 0 NUMBER = 1 .save .psect comdat ,rw,d,lcl,rel,con comhea: .blkw 1 comdat: .restore $comlas = comhea ; Generate first link .macro cmddef command,dispat,nargs,type=0 .save ; save current psect context .psect comdat ,rw,d,lcl,rel,con $$ = . ; Save current location .asciz /command/ ; Insert command text .even ; Always do this $com1 = . ; save current pc in 'comdat' .word 0 ; link to next is zero .word $$ ; Insert text address .word dispat ; Insert dispatch routine address .word nargs .word type .even ; must do $compc = . ; save the current pc . = $comlast ; backup to link word from previous .word $com1 ; insert address of new entry . = $compc ; restore correct pc $comlast = $com1 ; lastlink = current_entry .restore ; restore old psect context .endm ; thats it .macro strcat dst,src ; Concatonate two asciz string mov src ,-(sp) ; Stuff source address mov dst ,-(sp) ; Stuff destination jsr pc ,strcat ; Do it .globl strcat ; In case .endm strcat ; All done .macro strcmp s1,s2 ; Compare two asciz strings mov s2 ,-(sp) mov s1 ,-(sp) call strcmp .globl strcmp .endm strcmp .macro strcpy dst,src ; Copy asciz string mov src ,-(sp) mov dst ,-(sp) jsr pc ,strcpy .globl strcpy .endm strcpy .macro moverr e ; Die on error function movb e ,r0 ; If no error, all is well beq .+6 ; call error ; Error, it's fatal .endm moverr ; Thats all. .macro mapjcr job2,dst=r0 ; Insure JCR is currently mapped mov job2 ,-(sp) ; Do it call mapjcr ; Simple mov r0 ,dst ; Return address of it .endm mapjcr ; Done .macro getexec off,base,dst=r0 ; Get a word from executive mapped mov base ,r0 ; data (ie, first 20KW). .if nb, off ; Again, if offset is there, us add off ,r0 ; it else ignore it .endc ; Addressing for executive low add #20000 ,r0 ; memory is biased off of APR1 mov (r0) ,dst ; thus we add 20000 into every .endm getexec ; address. .macro save list ; Register saves, inline code. .if b , ; If no passed arguments then .ift ; recursivly call ourself to save ; generate the instructions. .iff ; Otherwise run through the .irp x, ; argument list. mov x,-(sp) ; .... .endr ; ..... .endc ; .endm save ; Alldone .macro unsave list ; Opposite of SAVE .if b , ; These two macros ARE order .ift ; dependent, ie: unsave ; SAVE .iff ; ..... .irp x, ; UNSAVE mov (sp)+,x ; Generate the code in-line .endr ; .endc ; .endm unsave ; All done .sbttl more macros .macro clrfqb ; Clear the FIRQB out call $clrfq ; Do it .endm clrfqb ; Thats all .macro clrxrb ; Clear the XRB out call $clrxr ; ... .endm clrxrb ; All done .macro putdec v ; Print a number on the terminal mov r0 ,-(sp) ; Save a register mov v ,r0 ; Stuff passed value into it call putdec ; Do the work mov (sp)+ ,r0 ; Pop something .endm putdec ; and all done .macro putoct v ; Save as PUTDEC but in octal mov r0 ,-(sp) ; format. Save a register mov v ,r0 ; Load value call putoct ; Dump and exit mov (sp)+ ,r0 ; Pop the register .endm putoct ; Done .macro getlin s ; Read a line from the terminal mov s ,-(sp) ; Stuff string address call getlin ; Call someone to read the data tst (sp)+ ; Pop arg .endm getlin ; Done .macro putbin s,l ; Dump (in pass-all mode) to .if b ,l ; the terminal. Can be invoked as: .ift ; PUTBIN #STRING clr -(sp) ; or: .iff ; PUTBIN #STRING,LENGTH mov l ,-(sp) ; Passed length, stuff it on stack .endc ; mov s ,-(sp) ; Push string address onto stack call putbin ; Dump it cmp (sp)+ ,(sp)+ ; Pop parameter list .endm putbin ; DonDYN MAC[.050038]DYN .MAC[.050036]    X14|H [4;Ik(&'( k ߫H&P` \RrPP2PPzPP{PPPPP2P~\$\\TD 0D \~ hi) +\ ^( n ^( np\^txY\^ˀ\!kVk<\F˰<˴ˬ\VVkˤ1`@lP ABCDEFGHIJKLMNOPQRSTUVWXYZ$.?0123456789<@<SЬTЬ UQS>?\\\\\\\\\`:#@'="\abcdefghi\\\\\\\jklmnopqr\\\\\\\~stuvwxyz\\\\\\\\\\\\\\\\\\\\\\{ABCDEFGHI\\\\\\}JKLMNOPQR\\\\\\\\STUVWXYZ\\\\\\0123456789\\\\\  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~@ggh<i|o<m<4p<p<k|Zn<l fr rwx<x<x<x޺<w@]@@fjnr]Ze@@|> | |v<H|  |  |xz|  |zt f r   < &^ @&@'*/V,"?Lh:hmBmz|z{x`y~|fN|@@|@͂|@ ݃ƃ<ns<|Ŏ |️|ep|u|-@率|<ᄇ2ֻr||ZRM | ntB|xyvZw|J=|R>|J? nnaa|bddf #5*60. ,r1 ; intervals for waiting to kill clr r0 ; Setup for divide div tim.sh ,r0 ; Get interval count mov r0 ,kiltmo ; Save it mov r0 ,kilcnt ; Init counter 10$: mov tim.sh ,XRB+0 ; Sleep .SLEEP ; Nap time call tmo$sh ; Go do some work call kill ; Perhaps delete jobs br 10$ ; Some more .save .psect rwdata ,d 200$: .asciz /Detaching/<15><12><15><12> .even .restore .dsabl lsb .sbttl More commands cmdkil: mov sp ,kildet ; For deleting detached jobs return ; Exit cmdhib: mov sp ,kildet mov sp ,hibreq return .enabl lsb cmdset: sub #120 ,sp ; Allocate a buffer mov sp ,r4 ; And a pointer for it clrb @r4 ; Null string mov #argptr ,r5 ; Argument pointers 10$: strcat r4 ,(r5)+ ; Move first arg into CMDBUF tst (r5) ; Move next arg address back beq 20$ ; And concat the next arg strcat r4 ,#200$ ; Stuff a space in there br 10$ ; Next please 20$: strcpy #cmdbuf ,r4 ; Copy back into command buffer call prsbuf ; Find the command tst r0 ; Success? beq 90$ ; No cmp 10(r1) ,#STRING ; Should we look for a value beq 30$ ; No getval argptr ; Yes, do it please bcs 90$ ; Oops 30$: mov 4(r1) ,r1 ; Go do the command jsr pc ,@r1 ; Call it br 100$ ; Exit 90$: putbin #210$ ; Error br 100$ ; Exit now 100$: add #120 ,sp ; Pop buffer and exit return .save .psect rwdata ,d 200$: .asciz / / 210$: .asciz /Bad SET command or bad number/<15><12> .even .restore .dsabl lsb .enabl lsb cmdbu1: mov #ddbur1 ,r1 br setpar cmdbu2: mov #ddbur2 ,r1 br setpar cmdbu3: mov #ddbur3 ,r1 br setpar cmdsle: mov #ddslp ,r1 br setpar setpar: getval argptr bcs 90$ mov r0 ,ddb(r1) putbin #210$ putdec ddb(r1) putbin #220$ br 100$ 90$: putbin #200$ 100$: return .save .psect rwdata ,d 200$: .asciz /Bad number/<15><12> 210$: .asciz /Parameter set to / 220$: .byte 15,12,0 .even .restore .dsabl lsb .sbttl getcmd .enabl lsb getcmd: putbin #200$ ; A prompt mov #cmdbuf ,r5 ; Point to a buffer getlin r5 ; Read something tst r0 ; Anything? beq 120$ ; No, the read failed prsbuf: mov #argptr ,r4 ; Arg pointers mov #cmdbuf ,r5 ; Point to a buffer clr (r4) ; Init the field clr r2 ; Arg count clr r3 ; Flag tstb @r5 ; Read ok, read anything? beq 110$ ; No 10$: tstb (r5) ; End of the line yet? beq 50$ ; Yes, exit please mov r3 ,(r4) ; Stuff new address for args? beq 15$ ; No tst (r4)+ ; Yes, and point to NEXT field clr (r4) ; Insure NEXT is NULL clr r3 ; No longer need new address inc r2 ; Count args 15$: cmpb (r5) ,#'A!40 ; Convert case? blo 20$ ; No cmpb (r5) ,#'Z!40 ; Well? bhi 20$ ; No bicb #40 ,(r5) ; Yep, make it upper case 20$: cmpb (r5) ,#40 ; A space in command line? bne 30$ ; No mov r5 ,r3 ; Get set to insert next addr clrb (r3)+ ; Yes, turn it into a NULL 30$: inc r5 ; Point to NEXT character br 10$ ; Get next character 50$: call findcm ; Get command matched up tst r0 ; Success bne 100$ ; Yes, exit putbin #210$ ; Nothing, error message time br 110$ ; Exit 100$: cmp r2 ,6(r1) ; Enough command line args? bge 105$ ; Yes putbin #220$ ; No, error time. clr r0 ; Failure 105$: return ; Bye 110$: clr r0 ; No data, return failure return 120$: exst$s #EX$SUC .save .psect rwdata ,d 200$: .asciz /DYN>/ 210$: .asciz /Unknown command/<15><12> 220$: .asciz /Insufficient arguments/<15><12> .even .restore .dsabl lsb findcm: mov r2 ,-(sp) ; Save this mov comhea ,r2 ; Get listhead for commands 10$: strcmp 2(r2) ,#cmdbuf ; Find the command? tst r0 ; Well? beq 100$ ; Yes, exit with address in R0 mov (r2) ,r2 ; No, get next command in the list bne 10$ ; Something was there clr r0 ; Failure br 110$ ; Exit 100$: mov 4(r2) ,r0 ; Success, return dispatch addr mov r2 ,r1 ; Return block address also 110$: mov (sp)+ ,r2 ; Pop it return ; Exit .sbttl init code DYN MAC[.050038]DYN .MAC[.050036]    X14|H [4;Ik(&'( k ߫H&P` \RrPP2PPzPP{PPPPP2P~\$\\TD 0D \~ hi) +\ ^( n ^( np\^txY\^ˀ\!kVk<\F˰<˴ˬ\VVkˤ1`@lP ABCDEFGHIJKLMNOPQRSTUVWXYZ$.?0123456789<@<SЬTЬ UQS>?\\\\\\\\\`:#@'="\abcdefghi\\\\\\\jklmnopqr\\\\\\\~stuvwxyz\\\\\\\\\\\\\\\\\\\\\\{ABCDEFGHI\\\\\\}JKLMNOPQR\\\\\\\\STUVWXYZ\\\\\\0123456789\\\\\  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~@ggh<i|o<m<4p<p<k|Zn<l fr rwx<x<x<x޺<w@]@@fjnr]Ze@@|> | |v<H|  |  |xz|  |zt f r   < &^ @&@'*/V,"?Lh:hmBmz|z{x`y~|fN|@@|@͂|@ ݃ƃ<ns<|Ŏ |️|ep|u|-@率|<ᄇ2ֻr||ZRM | ntB|xyvZw|J=|R>|J? nnaa|bddf .assume ddslp eq .assume ddbur1 eq .assume ddbur2 eq .assume ddbur3 eq .sbttl kill nonpriv detached jobs ; I know that we should base this on some job priv but ; this program must never exceed 4KW. Also, we are still ; using the old [1,*] convention. .iif ndf, MAXGRO ,MAXGRO = 10 kill:: tst kildet ; Delete things? beq 100$ ; No dec kilcnt ; Time to scan? bne 100$ ; No mov kiltmo ,kilcnt ; Yes, reset clr r5 ; Job number 10$: inc r5 ; Next job please CLRFQB ; Insure cleared out movb #UU.SYS ,FIRQB+FQFUN ; Get some job data movb r5 ,FIRQB+4 ; Insert JOB number .UUO ; Get the job data movb FIRQB ,r1 ; Success? bne 20$ ; No, ignore it bitb #200 ,FIRQB+5 ; Detached? beq 20$ ; No cmpb FIRQB+27,#MAXGRO ; Allowed to be detached? blos 20$ ; Yes, ignore ; tst hibreq ; Require job to be hibernating? beq 15$ ; No CLRFQB ; Insure cleared out movb #UU.SYS ,FIRQB+FQFUN ; Get some job data movb r5 ,FIRQB+4 ; Insert JOB number incb FIRQB+5 ; Subfuction 1 .UUO ; Get the job data movb FIRQB ,r1 ; Success? bne 20$ ; No, ignore it tst FIRQB+14 ; Is JBWAIT entry zero? bne 20$ ; No, not hibernating then ; 15$: CLRFQB ; Trash the firqb please movb #UU.CHU ,FIRQB+FQFUN ; Kill a job call movb r5 ,FIRQB+4 ; Job number to delete movb #377 ,FIRQB+35 ; Flag kill call .UUO ; Do it 20$: cmpb r1 ,#BADFUO ; Time to leave? bne 10$ ; No 100$: return ; Exit .sbttl timeouts ; tmo$sh ; ; r0 = unit number times 2 (always 0) ; r1 > ddb/fcb rot = 180. ; patchable, 'rot' cycle count tmo$sh::mov #ddb ,r1 ; Point to r/w data mov ddslp(r1),tim.sh ; reset the timeout please mov r0 ,-(sp) ; save a few registers mov r2 ,-(sp) ; mov r3 ,-(sp) ; mov r4 ,-(sp) mov r5 ,-(sp) ; clr r5 ; r5 is the current job number 10$: add #2 ,r5 ; next job please cmpb r5 ,myjob2 ; Don't fix myself up please beq 10$ ; Ignore getexec base=$jobtbl,off=r5,dst=r2 beq 10$ ; no job of this number active cmp r2 ,#-1 ; is this the end of jobtbl ? beq 20$ ; yes, so exit back to RSTS mov r1 ,r3 ; check to see if this job is the add r5 ,r3 ; same as one as last time to avoid cmp ddjobt(r3),r2 ; potential confict with 'ttijob' bne 15$ ; job creation in ttdvr. skip if ne mov r2 ,-(sp) ; call dyn ; no, check this job out please mov (sp)+ ,r2 ; 15$: mov r1 ,r3 ; save the jobs jdb address for the add r5 ,r3 ; next time thru mov r2 ,ddjobt(r3) ; save jdb address br 10$ ; next job please 20$: mov (sp)+ ,r5 ; pop the registers now please mov (sp)+ ,r4 ; mov (sp)+ ,r3 ; mov (sp)+ ,r2 ; mov (sp)+ ,r0 ; return ; for now .sbttl check out the current job (r2 > jdb) ; register usage ; ; r1 > ddb/fcb ; r2 > jdb+20000 ; r3 > jdb2 ; r4 > ddb + jobnumbertimes2 ; r5 = job number*2 dyn: add #20000 ,r2 ; Correct for APR1 biasing bit #JFNOPR ,JDFLG(r2) ; Job not logged in ? bne 100$ ; no, could have been 'ttijob' mov r1 ,r4 ; point to the timvec offset by add r5 ,r4 ; the job number times two. .IF NE ,R$$9.1 ; If 9.0 or 9.1, the JBD2 is .IFT ; in low core, else map the jcr mov JDJDB2(r2),r3 ; address of job's JDB2 block add #20000 ,r3 ; Correction for APR1 basing bit #1 ,r3 ; avoid crash if 'ttijob' was bne 100$ ; interupted in the middle. mov J2CPU(r3),r0 ; compute elasped cpu time. .IFF ; This must be 9.2 MAPJCR job2=r5 ; So thus map the user's JCR bit #1 ,r0 ; Insure valid please bne 100$ ; Not valid, then exit asap mov JCCPU(r0),r0 ; Fetch the cpu time. .ENDC ; mov r0 ,SAVTIM(r1) ; Save it please sub DDTIMV(r4),r0 ; subtract off time last used. mov r0 ,ELPTIM(r1) ; save elapsed cpu time now. .IF NE ,R$$9.1 ; Old RSTS/E today? .IFT ; Yes, priority is in the JDB clr r0 ; r3 now has pointer to jdb2 bisb JDPRI(r2),r0 ; the job's current priority .IFF ; No, we must map the JCR DYN MAC[.050038]DYN .MAC[.050036]    X14|H [4;Ik(&'( k ߫H&P` \RrPP2PPzPP{PPPPP2P~\$\\TD 0D \~ hi) +\ ^( n ^( np\^txY\^ˀ\!kVk<\F˰<˴ˬ\VVkˤ1`@lP ABCDEFGHIJKLMNOPQRSTUVWXYZ$.?0123456789<@<SЬTЬ UQS>?\\\\\\\\\`:#@'="\abcdefghi\\\\\\\jklmnopqr\\\\\\\~stuvwxyz\\\\\\\\\\\\\\\\\\\\\\{ABCDEFGHI\\\\\\}JKLMNOPQR\\\\\\\\STUVWXYZ\\\\\\0123456789\\\\\  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~@ggh<i|o<m<4p<p<k|Zn<l fr rwx<x<x<x޺<w@]@@fjnr]Ze@@|> | |v<H|  |  |xz|  |zt f r   < &^ @&@'*/V,"?Lh:hmBmz|z{x`y~|fN|@@|@͂|@ ݃ƃ<ns<|Ŏ |️|ep|u|-@率|<ᄇ2ֻr||ZRM | ntB|xyvZw|J=|R>|J? nnaa|bddfplease mov #FIRQB+FQFUN,r2 ; Setup to change the job settings movb #UU.PRI ,(r2)+ ; Stuff the subfunction code movb r5 ,(r2) ; Job number times 2 asrb (r2)+ ; But we don't want job*2 here incb (r2)+ ; We want to change the priority movb (sp)+ ,(r2)+ ; The new priority setup movb r0 ,1(r2) ; New run burst beq 10$ ; Don't change it incb (r2) ; Flag we want to change it 10$: .UUO ; At last .br skipjb skipjb: mov SAVTIM(r1),DDTIMV(r4) ; save the current cpu time return ; at last .sbttl odds and ends $clrxr::save ; Clear the XRB out mov #xrb ,r0 ; Point to it 10$: clr (r0)+ ; Clear a word cmp r0 ,#xrb+14 ; See if done blos 10$ ; Not yet, try again unsave ; Pop registers return ; and exit $clrfq::save mov #FIRQB ,r0 10$: clr (r0)+ cmp r0 ,#FIRQB+36 blos 10$ unsave return putoct: save mov #$cbomg ,r3 br pcom putdec: save mov #$cbdmg ,r3 pcom: save sub #20 ,sp mov r0 ,r1 mov sp ,r0 clr r2 jsr pc ,@r3 mov r0 ,r1 mov sp ,r0 sub r0 ,r1 qiow$s #io.wal,#5,,,,, add #20 ,sp unsave return putbin: save mov 2+4(sp) ,r0 mov 4+4(sp) ,r1 bne 20$ mov r0 ,r1 10$: tstb (r1)+ bne 10$ sub r0 ,r1 dec r1 20$: qiow$s #io.wal,#5,,,,, ; rsx and p/os unsave return .enabl lsb error: putbin #200$ ; VERY crude error reporting putdec r0 putbin #210$ exst$s #EX$SEV .save .psect rwdata ,d 200$: .asciz /Exec directive returned error / 210$: .byte cr,lf,0 .even .restore .dsabl lsb .enabl lsb getlin: mov 2(sp) ,r0 ; Read a command line QIOW$S #io.rvb,#5,,,#kbiost,, cmpb kbiost ,#IS.SUC bne 100$ add kbiost+2,r0 clrb (r0) mov #1 ,r0 br 110$ 100$: movb #32 ,(r0)+ clrb (r0) clr r0 110$: putbin #200$ return .save .psect rwdata ,d 200$: .byte 12,0 .restore .dsabl lsb .sbttl strcat and strcpy ; input: ; 0(sp) return address ; 2(sp) dst address ; 4(sp) src address ; output: r0 dest address strcpy::save ; save temp registers please mov 2+2(sp) ,r0 ; destination address mov 2+4(sp) ,r1 ; source .asciz address 10$: movb (r1)+ ,(r0)+ ; copy until a null bne 10$ ; not done mov 2+2(sp) ,r0 ; return the dst address unsave ; pop r1 and exit mov (sp) ,4(sp) ; move return address up now cmp (sp)+ ,(sp)+ ; pop junk and exit return strcat::save ; save temp registers please mov 2+2(sp) ,r0 ; destination address mov 2+4(sp) ,r1 ; source .asciz address 5$: tstb (r0)+ ; look for the end of the dst string bne 5$ ; not found yet dec r0 ; found it, fix the pointer 10$: movb (r1)+ ,(r0)+ ; copy until a null bne 10$ ; not done mov 2+2(sp) ,r0 ; return the dst address unsave ; pop r1 and exit mov (sp) ,4(sp) ; move return address up now cmp (sp)+ ,(sp)+ ; pop junk and exit return strcmp::mov 2(sp) ,r0 ; Pick up 'a' mov 4(sp) ,r1 ; And 'b' 10$: cmpb (r0)+ ,(r1) ; Are they the same bne 20$ ; No tstb (r1)+ ; At the end of the string bne 10$ ; No clr r0 ; Equal return br 100$ 20$: blo 30$ ; Br if ab return br 100$ 30$: mov #-1 ,r0 ; A ; Save temps clr r1 ; Init accum 5$: cmpb @r0 ,#40 ; Eat leading spaces bne 10$ ; No inc r0 ; Next br 5$ ; ... 10$: clr -(sp) ; Positive cmpb @r0 ,#'- ; Leading minus sign? bne 20$ ; No com (sp) ; Yes, flag inc r0 ; Next char now 20$: tstb @r0 ; End of it all ? beq 100$ ; Yes, exit cmpb @r0 ,#'0 ; In range ? blo 90$ ; No, thats an error cmpb @r0 ,#'9 ; Keep looking bhi 90$ ; Error again mul #12 ,r1 ; Ok, shift over old number bvs 90$ ; Overflowed movb (r0)+ ,r2 ; Get number subDYN MAC[.050038]DYN .MAC[.050036]    X14|H [4;Ik(&'( k ߫H&P` \RrPP2PPzPP{PPPPP2P~\$\\TD 0D \~ hi) +\ ^( n ^( np\^txY\^ˀ\!kVk<\F˰<˴ˬ\VVkˤ1`@lP ABCDEFGHIJKLMNOPQRSTUVWXYZ$.?0123456789<@<SЬTЬ UQS>?\\\\\\\\\`:#@'="\abcdefghi\\\\\\\jklmnopqr\\\\\\\~stuvwxyz\\\\\\\\\\\\\\\\\\\\\\{ABCDEFGHI\\\\\\}JKLMNOPQR\\\\\\\\STUVWXYZ\\\\\\0123456789\\\\\  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~@ggh<i|o<m<4p<p<k|Zn<l fr rwx<x<x<x޺<w@]@@fjnr]Ze@@|> | |v<H|  |  |xz|  |zt f r   < &^ @&@'*/V,"?Lh:hmBmz|z{x`y~|fN|@@|@͂|@ ݃ƃ<ns<|Ŏ |️|ep|u|-@率|<ᄇ2ֻr||ZRM | ntB|xyvZw|J=|R>|J? nnaa|bddf #'0 ,r2 ; Convert add r2 ,r1 ; And add the digit in bcc 20$ ; Ok, get another digit 90$: tst (sp)+ ; Pop sign indicator sec ; Error exit br 120$ ; Exit 100$: mov r1 ,r0 ; Success, return result tst (sp)+ ; Negative?? beq 110$ ; No neg r0 ; Make < 0 110$: clc ; Clear for success 120$: unsave ; Pop registers and exit return ; Bye crlfou: putbin #crlf ; Simple carriage return/line feed return ; Dumper .save ; Save current psect context .psect rwdata ,d ; Switch to data space psect crlf: .byte 15,12,0 ; Data .even ; Nice to use word boundaries .restore ; Pop back to code psect .end start