Skip to main content
4 of 4
Typo' fix.
TonyM
  • 4.7k
  • 1
  • 23
  • 35

It's a consequence of author Sophie Wilson's neat work in squashing the Machine Operating System (MOS) code to save its precious ROM space and get it as fast as possible. The CR/LF sequence would need more ROM space and be slightly slower.

To write a character to the current stream, programs call the 'OS write character' function OSWRCH at address &FFEE. This just writes the byte in A while preserving all 6502 registers (A, X, Y). At &FFEE there's just an indirect jump through the WRCHV vector to the actual routine.

To write an ASCII character, there's a separate function called OSASCI at address FFE3. This writes the byte in A while preserving all 6502 registers, like OSWRCH, but it also expands an ASCII Carriage Return (CR) into the LF/CR sequence.

By using the LF/CR sequence, the OSASCI routine can flow into the OSWRCH routine. The actual software in the MOS is as follows:

FFE3    OSASCI    CMP     #&0D       ;Do an OSWRCH unless this is a CR.
FFE5              BNE     &FFEE
FFE7              LDA     #&0A       ;Got a CR. Use OSWRCH to write LF first.
FFE9              JSR     FFEE
FFEC              LDA     #&0D       ;Now fall into OSWRCH to write CR and exit.
FFEE    OSWRCH    JMP     (&020E)    ;Jump through vector to routine.

(This routine had already been used in their preceding Acorn Atom computer, at different ROM call addresses.)

Because A must be preserved, doing the LF first allows the fall into OSWRCH to occur with the A holding the original called value of &0D (CR).

If the routine tried to do CR/LF, it would need to be larger to call OSWRCH twice then restore A to the original call value. It'd be something like this:

FFDF    OSASCI    CMP     #&0D       ;Do an OSWRCH unless this is a CR.
FFE1              BNE     &FFEE
FFE3              JSR     FFEE       ;Got a CR. Use OSWRCH to it first.   
FFE6              LDA     #&0A       ;Now use OSWRCH to write the LF second.
FFE8              JSR     FFEE
FFEB              LDA     #&0D       ;Restore A and exit.
FFED              RTS
FFEE    OSWRCH    JMP     (&020E)    ;Jump through vector to routine.

Because a JSR to OSWRCH is needed then an RTS, the routine is 4 bytes longer and is slower.

With a CPU that was already slow, though relatively swift for its market at that time, its important to shave off wasted cycles wherever possible on routines that get called repetitively. Here it's a small part of the overall routine. But all the little slow bits add up to a slow system. A goal of Sophie and of the Acorn team was to get their software speed up, that's apparent in the work put into their BASIC and OS software to make it fast.

In the days when they took this decision, it didn't cause anyone problems. The bytes would only be going to their screen routines, to a printer or staying inside BBC Micro/Master/Atom files used at most by other BBC Micros/Masters/Atoms.

I first noticed this in the mid-80s, when reading the BBC Micro Advanced User Guide then disassembling the MOS. It struck me then as a neat way of trimming the routine down and getting the speed up a little.

TonyM
  • 4.7k
  • 1
  • 23
  • 35