!lm10
!rm76
A New, Fancier .AS Directive

Many times I write text printing loops that depend on the sign bit of each byte to indicate the end of text.  I might set up the text this way:

     .AS /THIS IS THE TEXT I WANT TO PRIN
     .AS -/T/

This assembles with the sign bits off (0) on all the characters of the text except the last one.  I can terminate my printing loop by testing that bit.  A little later, I will show you an example of just such a loop.

But when there are many messages, I get tired of using separate lines for the last character of each message!  Why not have an assembler directive which automatically sets the sign bit of the last character the opposite of the sign bits of the rest of the message?  Since Version 4.0 of the S-C Assembler II has a .US directive for me, the user, to program....

The only problem is that how to program for the .US directive has never been revealed.  Until now.

The following little program will implement just the directive I want, and install it as the .US directive.  It uses five programs inside the assembler (see lines 1100-1140).  The code is patterned directly after the code for the .AS directive, which starts at $203C in most copies of Version 4.0.
!lm15
!rm71

NOTE:  You should check your assembler to make sure that the four bytes starting at $203C are "A0 00 84 04"; if they are, you can use the same addresses for the five routines as I have shown here.  (If not, send me your original Version 4.0 disk for a free update.  Be sure to adequately protect the disk for shipping, because your new copy will come back on the same disk.)
!lm10
!rm76

Line 1000 sets the origin of the code to $0F00.  You could use some other origin, like $0300, if you wish.  Just be sure it is an area of memory that you will not be using for some other purpose wile you are assembling.  Line 1010 directs the object code to a BRUNnable file named B.US.DIRECTIVE.

The code from 1160 to 1210 is executed when you BRUN B.US.DIRECTIVE.  It stores the address of DIR.US in the .US vector at the beginning of the assembler.  You can read a little about this on page 15 of the Version 4.0 update manual.

Lines 1030-1050 define a few variables.  WBUF is the line buffer the assembler uses, starting at $0200.  The assembler unpacks a line from the source code into this buffer, and then proceeds to analyze it.  DLIM and HIBIT are temporary locations in page zero where I will save the delimiter character and the high-bit setting.
!np
The meat of the directive is in lines 1230-1510.  If you disassemble the code at $203C in the S-C Assembler II, you will see a marked similarity here.  You might also try disassembling the code for the GNNB and GNC subroutines.

GNC retrieves the next character from WBUF and increments the pointer.  The character is tested.  Carry status is set if the end-of-line token was picked up.  Equal status is set if a blank or end-of-line token was picked up.  GNNB calls on GNC until a non-blank character is found.  GNC returns with the character in the A-register, and the pointer to the next character in the Y-register.

Lines 1240-1310 scan from the end of the opcode field to try to find the delimiter.  If no non-blank character is found after the opcode field, you will get the "BAD ADDRESS ERROR".  If a minus sign is found, $80 is stored in HIBIT instead of $00.  This value will be merged with every character between the delimiters, to set or clear the high-bit of each byte.  When the delimiter is found, it is stored in DLIM.

Lines 1320-1350 check to make sure that there are some characters after the delimiter before the next occurrence of the delimiter.  For example, if you write ".US //", I want to assemble no bytes and go on.  If I find the end-of-line token, you will get the error message.

Lines 1360-1430 are a loop to output the bytes one by one.  I have to look ahead to see if the next character is the delimiter again.  If not, then I will output the current character (by now accessed with "LDA WBUF-2,Y", because Y has been advanced).  If the next one is the delimiter, then the current one is the last character of the string; I will have to go to ".3", to handle the last character.

Lines 1450-1490 handle the last character of the string between the delimiters.  The high-bit is first set just like all the rest of the bytes at line 1460, and then reversed with the EOR #$80 at line 1470.

There is no end to the detail we could get into by describing how EMIT, CMNT, and ERBA work.  I will leave them for you to puzzle over at your leisure.  (Can't give away the whole plot in chapter 1!)

<code for dir.us>

The following program shows how I might use the new .US directive I have just built.  It prints the line of text from line 1230 ten times on the screen.  The .US directive assures that I can tell when I am at the end of the text string by looking at the sign bit.  That is just what the BMI opcode at line 1110 is doing.  Lines 1070, 1080, 1190, and 1200 are the looping code to make ten copies of the line.  Lines 1090-1150 print the message except for the last character; lines 1170-1180 print that last character and a carriage return.
