\ a suitable location in zero page pr=&70 \ some standard MOS calls osnewl=&FFE7 osasci=&FFE3 gsinit=&FFC2 \ start of ROM header EQUW &00 EQUB &00 JMP service EQUB &82 EQUB copy-&8000 EQUB &01 .title EQUS "Example ROM 1" EQUB 0 .version EQUS "1.00" .copy EQUB 0 EQUS "(C) 2001 Mark Bush" EQUB 0 \ service entry point .service CMP #&09 BEQ help RTS \ help routine .help JSR gsinit \ Y contains offset of first non space after "HELP" \ A contains that character \ this will be a carriage return if there are no arguments CMP #&0D BEQ help2 \ no arguments so we will respond LDA #&09 \ restore service number RTS \ display our title and version .help2 TYA PHA \ preserve Y for other ROMS to respond to this call JSR osnewl LDX #title MOD 256 LDY #title DIV 256 JSR print \ display our title LDA #&20 \ space character JSR osasci LDX #version MOD 256 LDY #version DIV 256 JSR print \ display our version JSR osnewl PLA TAY LDA #&09 \ restore A and Y RTS \ print string pointed to by (Y;X) \ string will be terminated by \ a control char (always 0 in this example) .print \ preserve previous contents of pr;pr+1 LDA pr PHA LDA pr+1 PHA \ store location of string to print STX pr STY pr+1 LDY #&00 \ Y is offset of current character to print .ploop LDA (pr),Y CMP #&20 \ terminate on control character BCC donep JSR osasci INY BNE ploop \ print at most 256 characters - prevents runaway strings .donep \ restore contents of pr;pr+1 PLA STA pr+1 PLA STA pr RTS
Phew! As we can see, as soon as we start actually doing something useful, the size of the code increases dramatically. From now on, we will not include the full text of examples, but use a link to the code which you can download and peruse at your leisure.
The first line sets "pr" to point to a location in zero page. BASIC reserves &70 to &8F for user programs. Since you are likely to enter this program from a BASIC program, these locations should be available for use, though since we take care to save and restore the contents when we use the address, this does not matter too much. A zero page location is required for doing the type of indexed, indirect addressing used here.
The next three lines give us a way to refer to three OS routines we need. You may be familiar with OSNEWL (which just prints a newline) and OSASCI (which prints the character in the accumulator). The GSINIT routine can be very usefull when parsing command lines. It uses &f2;&f3 and the Y register and increments Y until it has moved passed any spaces, etc, on the command line. Thus, afterwards, Y will either point to a carriage return (marking the end of the line) or to the first character of the next word. The accumulator will hold that next character.
In our example, we do not want to respond to "*HELP" if there are arguments, so if the next character after calling GSINIT is not a carriage return we ignore the command and return. We restore the service number (which we know to be &09) in the accumulator and return. Note that we do not need to worry that we may have altered the contents of Y. It now points at the first character of the next word on the command line which is what any other help service routine will need anyway.
For the help routine proper, we do need to preserve Y (but not X in this case) so we push its value onto the stack. We print a newline to give our help message some space below any previous message, then we load X and Y with the low byte and high byte of the address of the title and execute the print subroutine. We print a space, then call the print subroutine again using the address of the version string. We then restore the value of Y and reset the accumulator to the help service number and exit.
The print routine is fairly simple and makes use of the fact that any string to be printed will be followed by a zero (in fact we allow any control character to terminate the string). The routine first pushes the contents of &70 and &71 onto the stack to preserve their contents. We then store the address of the string to print (known to be in the X and Y registers) into these zero page locations and use the Y register to index over the string. We continue printing characters, incrementing Y, until we reach a character less than &20 (a space). Note the use of "BCC" here which will branch if the accumulator is less than the compared value. We also use "BNE" after incrementing Y so that we will print at most 256 characters. This helps guard against runaway strings. Before exiting, we pop the previous contents of &70 and &71 from the stack.