uknown osword handler in service rom

discussion of beeb/electron applications, languages, utils and educational s/w
Post Reply
dominicbeesley
Posts: 799
Joined: Tue Apr 30, 2013 11:16 am
Contact:

uknown osword handler in service rom

Post by dominicbeesley » Fri Jul 05, 2019 5:46 pm

Hello,

I'm writing a hardware support ROM and I'd like to add a few OSBYTE/WORDs. Some of the operations I'm doing may take a long time so I'd like to re-enable interrupts in my code.

I'd be grateful if anyone could give feedback on my assumptions:

- interrupts are disabled when service call 8 is passed round?
- I can safely use &EF, &F0, &F1 in my routine *until* I enable interrupts, at which point they might be corrupted
- If I enable interrupts I have to save and restore &F0 as this is used to restore X
- if I want to return a value in X I should save this in F0?
- if I want to return a value in Y I can just set Y?

Questions:
- Will the above work on all versions of MOS (it looks like it should on 1.20)
- It looks from the disassembly of OS 1.20 that X,Y,A get trashed if no OSBYTE/WORD matches - is this right?
- Should I preserve EF and F1 as well when reenabling interrupts

Ta

D

User avatar
jgharston
Posts: 3596
Joined: Thu Sep 24, 2009 11:22 am
Location: Whitby/Sheffield
Contact:

Re: uknown osword handler in service rom

Post by jgharston » Fri Jul 05, 2019 10:31 pm

dominicbeesley wrote:
Fri Jul 05, 2019 5:46 pm
- interrupts are disabled when service call 8 is passed round?
- I can safely use &EF, &F0, &F1 in my routine *until* I enable interrupts, at which point they might be corrupted
- If I enable interrupts I have to save and restore &F0 as this is used to restore X
- if I want to return a value in X I should save this in F0?
- if I want to return a value in Y I can just set Y?

Questions:
- Will the above work on all versions of MOS (it looks like it should on 1.20)
- It looks from the disassembly of OS 1.20 that X,Y,A get trashed if no OSBYTE/WORD matches - is this right?
- Should I preserve EF and F1 as well when reenabling interrupts
You're right, interupts are disabled during OSBYTE/OSWORD, that's a bit of a surprise as that would slow the entire system down unneccessarily. The Beeb normally only ever disables interupts when it absolutely really needs to, not on a whim.

However, you are safe to enable interupts during your code, as interupts aren't allowed to mess with &EF/F0/F1 as they are foreground workspace. If interupts are going to call OSBYTE or OSWORD, they need to be very careful what they are doing, and must save/restore &EF/F0/F1 around the calls as the interupt may be in the middle of an OSBYTE/OSWORD.

Your service routine is passed its parameters in &EF,F0,F1, not A,X,Y. Y happens to be a copy of &F1, and as you return Y in the Y register its acceptable to use it as an input parameter.

For your OSWORD handler, (&F0),offset points to your control block. You return data from an OSWORD call in the control block, never in the registers. OSWORD control blocks for calls<128 are 16 bytes, OSWORD control block sizes for calls>127 are specified in the first two bytes.

You return data from OSBYTE <128 in &F0 to return to the user in the X register, you return data from OSBYTE >127 in &F0 and Y to return to the user in X and Y.

&EF/F0/F1 are always initialised by the OSBYTE/OSWORD dispatch code to A,X,Y on entry to OSWORD/OSBYTE. You can depend on them being set to those specific values, not trashed.

Bear in mind that if you make ***ANY*** call to ***ANY**** code that is not your code, you lose ownership of &EF/F0/F1 as you have no ability to tell that that call may end up somewhere that uses them. So, if you want to, eg, call OSARGS or OSFILE or OSCLI etc or even any random bit of code that is not your code, you must expect EF/F0/F1 to be trashed on return as whatever you've called is highly likely to make OSBYTE/OSWORD calls itself.

The only exception is that interupts are not allowed to trash EF/F0/F1. Eg, keyboard insert calls INSV, it doesn't call the OSBYTE veneer, sound processing calls REMV, it doesn't call the OSBYTE ADVAL call.

A useful hint for any service handler. X *always* holds the ROM number, so it can be trashed as you can always fetch it from &F4. On return the first thing the MOS does is trash the X register (to test if A is zero), so on return you don't need to ensure X holds anything in particular.

Also, nothing is passed or returned in the flags, so there's no need for the code I keep seeing in service handlers that saves and restores all four registers. All that comes in is A and Y, all that goes out is A and Y.
Last edited by jgharston on Fri Jul 05, 2019 10:32 pm, edited 1 time in total.

Code: Select all

$ bbcbasic
PDP11 BBC BASIC IV Version 0.25
(C) Copyright J.G.Harston 1989,2005-2015
>_

User avatar
jgharston
Posts: 3596
Joined: Thu Sep 24, 2009 11:22 am
Location: Whitby/Sheffield
Contact:

Re: uknown osword handler in service rom

Post by jgharston » Fri Jul 05, 2019 11:07 pm

Let's turn this into a bit of a tutorial. :)

Let's take SoftRTC which uses the TIME clock to implement an OSWORD 14 Real Time Clock. It is coded (a bit) like this:

Code: Select all

.Service
CMP #8:BNE NotServ8
LDA &EF:CMP #14:BEQ Osword14
.NotOsword14
LDA #8:RTS               \ Not OSWORD 14
.Osword14
\ (&F0) points to the control block
LDY #0:LDA (&F0),Y       \ Get OSWORD 14 command
CMP #0:BNE NotOsword14   \ We are only going to implement OSWORD 14,0
\
\ We're going to use the control block we've been passed as our workspace
LDX &F0:LDY &F1          \ XY=> points to the control block
LDA #1:JSR OSWORD        \ Read TIME
\ Now, we know that &F0/F1 will have been set to point to the control block, so from our
\ perspective they have been preserved, because we have used the control block we were
\ passed to make the OSWORD 1 call.
\
\ ...do some funky arithmetic...
\
LDA whatever:LDY #offset:STA (&F0),Y \ Store returned data in control block
LDA whatever:LDY #offset:STA (&F0),Y
LDA whatever:LDY #offset:STA (&F0),Y
LDA #0:RTS                           \ Claim the call
Now, suppose SoftRTC needed to check what machine it was called on, by calling OSBYTE 0. For example, the Compact calls the NFS if no sideways ROM responds, and you might want to do something special in that case. That call to OSBYTE 0 will change EF/F0/F1, so you'd have to do:

Code: Select all

\ (&F0) points to the control block
LDY #0:LDA (&F0),Y       \ Get OSWORD 14 command
CMP #0:BNE NotOsword14   \ We are only going to implement OSWORD 14,0
LDA &F1:PHA:LDA &F0:PHA  \ Save F0/F1
LDA #0:LDX #1:JSR OSBYTE \ What machine am I on?
PLA:STA &F0:PLA:STA &F1  \ Restore F0/F1
CPX #5:BEQ Somethingelse
As OSBYTEs and OSWORDs never return anything in A (they are defined to preserve A*), you could use a subroutine to do the save/call/restore, eg:

.CallOsbyteLow
\ Y=osbyte number (must be <128), X=parameter
LDA &F1:PHA:LDA &F0:PHA \ Save F0/F1, trashing A
TYA:JSR OSBYTE \ Make an OSBYTE A,X call
PLA:STA &F0:PLA:STA &F1 \ Restore F0/F1
RTS

It's a bit fiddlier for high numbered OSBYTEs as you're passing X and Y, so you have nowhere to put A while saving F0 and F1. Though, as EF will immediately by used to store A (and interupts aren't allowed to trash EF/F0/F1, so it won't change in the background), you could do:

.CallOsbyte
\ A,X,Y=osbyte parameters
STA &EF \ Save A in the Asave workspace
LDA &F1:PHA:LDA &F0:PHA \ Save F0/F1, trashing A
LDA &EF:JSR OSBYTE \ Make an OSBYTE call
PLA:STA &F0:PLA:STA &F1 \ Restore F0/F1
RTS


*Note, the memory size OSBYTEs 82/83/84 are an exception, but they can be ignore for the purpose of this discussion.
Last edited by jgharston on Fri Jul 05, 2019 11:21 pm, edited 3 times in total.

Code: Select all

$ bbcbasic
PDP11 BBC BASIC IV Version 0.25
(C) Copyright J.G.Harston 1989,2005-2015
>_

User avatar
jgharston
Posts: 3596
Joined: Thu Sep 24, 2009 11:22 am
Location: Whitby/Sheffield
Contact:

Re: uknown osword handler in service rom

Post by jgharston » Fri Jul 05, 2019 11:15 pm

Remember, you lose ownership of EF/F0/F1 whenever you call code that you don't own.

Take a hypothetical PrettyPrint OSWORD that takes a string, fiddles with it, and prints it in a "pretty" way. Whenever it calls OSWRCH you have to assume you lose ef/f0/f1, so you need code along these lines:

Code: Select all

.OswordPrettyPrint
\ (&F0) points to the control block
LDY #0:LDA (&F0),Y:TAX   \ Get size of control block
DEX:DEX                  \ Step past header
LDY #2                   \ Point to start of string
.loop
LDA &F1:PHA:LDA &F0:PHA  \ Save pointer to control block
LDA (&F0),Y              \ Get character
\ do some stuff with it
JSR OSWRCH               \ Print it, trashing EF/F0/F1
PLA:STA &F0:PLA:STA &F1  \ Restore pointer to control block
INY                      \ Point to next character
DEX:BNE loop             \ Loop for whole control block
Something to note is that you very rarely need to preserve &EF. Once you've checked it for the call number you are responding to, then you don't need it's contents any more.

Code: Select all

$ bbcbasic
PDP11 BBC BASIC IV Version 0.25
(C) Copyright J.G.Harston 1989,2005-2015
>_

dominicbeesley
Posts: 799
Joined: Tue Apr 30, 2013 11:16 am
Contact:

Re: uknown osword handler in service rom

Post by dominicbeesley » Fri Jul 05, 2019 11:56 pm

Thanks for all this... I'll try and get a read through it all tomorrow.

D

dominicbeesley
Posts: 799
Joined: Tue Apr 30, 2013 11:16 am
Contact:

Re: uknown osword handler in service rom

Post by dominicbeesley » Mon Jul 08, 2019 10:25 am

Thanks that all makes sense and seems to work for me though I've only got this working in a sketchy way.
However, you are safe to enable interupts during your code, as interupts aren't allowed to mess with &EF/F0/F1 as they are foreground workspace. If interupts are going to call OSBYTE or OSWORD, they need to be very careful what they are doing, and must save/restore &EF/F0/F1 around the calls as the interupt may be in the middle of an OSBYTE/OSWORD.
Is the foreground workspace thing documented anywhere i.e. which regs are/aren't allowed in interrupts?

D

User avatar
jgharston
Posts: 3596
Joined: Thu Sep 24, 2009 11:22 am
Location: Whitby/Sheffield
Contact:

Re: uknown osword handler in service rom

Post by jgharston » Mon Jul 08, 2019 6:18 pm

dominicbeesley wrote:
Mon Jul 08, 2019 10:25 am
Is the foreground workspace thing documented anywhere i.e. which regs are/aren't allowed in interrupts?
Presuming you mean memory locations... ;)
ALL memory locations are not allowed to be messed with by interupts*, and must be preserved and restored if used in the background, except the interupt workspace at &FA/B/C. Conversely, foreground code must not mess with the interupt workspace as an interupt may go past and change it underneath your feet. AllMem

*Other than of course, an interupt whose task is explictly to change memory - such as insert into a buffer, load data from a disk sector or a passing network packet.

Code: Select all

$ bbcbasic
PDP11 BBC BASIC IV Version 0.25
(C) Copyright J.G.Harston 1989,2005-2015
>_

dominicbeesley
Posts: 799
Joined: Tue Apr 30, 2013 11:16 am
Contact:

Re: uknown osword handler in service rom

Post by dominicbeesley » Wed Jul 10, 2019 9:49 am

Thanks JGH for the help so far

A couple more questions/clarifications on this:

1) V flag and OSBYTE/WORD - looking at the handler it seems that the V flag is set on exit for an unrecognised OSBYTE/WORD but this is neither documented in the AUG or on MDFS.net however it does seem to be used in application software i.e. */AMPLE

Code: Select all

        lda     #$6F                            ; 10EC A9 6F                    .o
        ldx     #$40                            ; 10EE A2 40                    .@
        jsr     OSBYTE                          ; 10F0 20 F4 FF                  ..
        lda     #$6F                            ; 10F3 A9 6F                    .o
        bvc     L10F9                           ; 10F5 50 02                    P.
        lda     #$00                            ; 10F7 A9 00                    ..
L10F9:  sta     $0CFA                           ; 10F9 8D FA 0C                 ...
[detecting presence of OSBYTE 6F]

So is this true on later MOS versions? Should the documentation be updated on mdfs.net?

2) It seems your rule of not calling OSBYTE in interrupts is not followed by application software i.e. AMPLE(again)

Code: Select all

; ----------------------------------------------------------------------------
L0E50:  lda     zp_mos_INT_A                    ; 0E50 A5 FC                    ..
        pha                                     ; 0E52 48                       H
        txa                                     ; 0E53 8A                       .
        pha                                     ; 0E54 48                       H
L0E55:  tya                                     ; 0E55 98                       .
        pha                                     ; 0E56 48                       H
        lda     $0CFA                           ; 0E57 AD FA 0C                 ...
        beq     L0E61                           ; 0E5A F0 05                    ..
        ldx     #$81                            ; 0E5C A2 81                    ..
        jsr     OSBYTE                          ; 0E5E 20 F4 FF                  ..
L0E61:  lda     sheila_SYSVIA_ifr               ; 0E61 AD 4D FE                 .M.
        pha                                     ; 0E64 48                       H
        lda     #$10                            ; 0E65 A9 10                    ..
        pha                                     ; 0E67 48                       H
        lda     #$C0                            ; 0E68 A9 C0                    ..
        pha                                     ; 0E6A 48                       H
        php                                     ; 0E6B 08                       .
        jmp     (L008A)                         ; 0E6C 6C 8A 00                 l..
[Part of the AMPLE interrupt handler, which calls OSBYTE!]

So it seems your assertion
However, you are safe to enable interupts during your code, as interupts aren't allowed to mess with &EF/F0/F1 as they are foreground workspace.
is not quite true. Your rules aren't followed by other applications and so I can't re-enable interrupts and use EF/F0/F1 if I want my code to work with Ample.

I suspect that other applications will do this too, indeed the AUGs (New/original) have slightly different advice. The _New_ says NOT to call OS routines where as the original AUG says ".. should not call any operating system routines if at all possible.".

So I think to make my ROM more likely to work it can't rely on F0/F1 while interrupts are enabled and needs to save / restore for safety, which is a faff but not a show stopper as I'm only going to be re-enabling interrupts.

D
Last edited by dominicbeesley on Wed Jul 10, 2019 9:50 am, edited 1 time in total.

dominicbeesley
Posts: 799
Joined: Tue Apr 30, 2013 11:16 am
Contact:

Re: uknown osword handler in service rom

Post by dominicbeesley » Sun Jul 14, 2019 7:43 am

So has anyone else seen examples of testing v after a call to osbyte? Is it a valid way to test for the presence of a rom?

User avatar
dv8
Posts: 229
Joined: Mon Jun 22, 2009 9:07 pm
Contact:

Re: uknown osword handler in service rom

Post by dv8 » Sun Jul 14, 2019 9:19 am

dominicbeesley wrote:
Sun Jul 14, 2019 7:43 am
So has anyone else seen examples of testing v after a call to osbyte? Is it a valid way to test for the presence of a rom?
I've used it a few times before. This use of the V flag is consistent across all versions of the OS so it's a valid way to test for the presence of a feature (it doesn't necessarily need to be serviced by a ROM).

The OS itself relies on this behaviour. For example *FX calls OSBYTE then tests the V flag on exit. If V=1 it displays the 'Bad command' error message.

dominicbeesley
Posts: 799
Joined: Tue Apr 30, 2013 11:16 am
Contact:

Re: uknown osword handler in service rom

Post by dominicbeesley » Sun Jul 14, 2019 11:59 am

Thanks this will save a bit of space for me in some of my code!

D

User avatar
jgharston
Posts: 3596
Joined: Thu Sep 24, 2009 11:22 am
Location: Whitby/Sheffield
Contact:

Re: uknown osword handler in service rom

Post by jgharston » Sun Jul 14, 2019 1:23 pm

dominicbeesley wrote:
Wed Jul 10, 2019 9:49 am
Thanks JGH for the help so far
A couple more questions/clarifications on this:
1) V flag and OSBYTE/WORD - looking at the handler it seems that the V flag is set on exit for an unrecognised OSBYTE/WORD but this is neither documented in the AUG or on MDFS.net however it does seem to be used in application software i.e. */AMPLE
It's not documented because it is internal to the MOS and to the MOS only. It allows *FX to generate Bad Command when there is no respondant. You MUST NOT rely on it when the call exists the MOS and the only defined return values are X,Y,Cy for OSBYTE and control block contents for OSWORD. You test if your OSWORD call has been implemented by checking that the data you want has been supplied in the control block, you test if your OSBYTE call has been implemented by checking the values of the returned registers. Specifically, X will be &FF if nobody responded and will be whatever the responder supplied if something responds.

Code: Select all

        lda     #$6F                            ; 10EC A9 6F                    .o
        ldx     #$40                            ; 10EE A2 40                    .@
        jsr     OSBYTE                          ; 10F0 20 F4 FF                  ..
        lda     #$6F                            ; 10F3 A9 6F                    .o
        bvc     L10F9                           ; 10F5 50 02                    P.
        lda     #$00                            ; 10F7 A9 00                    ..
L10F9:  sta     $0CFA                           ; 10F9 8D FA 0C                 ...
That code should be testing the returned X value. See the Wiki article on Paging in video memory.
dominicbeesley wrote:
Wed Jul 10, 2019 9:49 am
2) It seems your rule of not calling OSBYTE in interrupts is not followed by application software i.e. AMPLE(again)

Code: Select all

; ----------------------------------------------------------------------------
L0E50:  lda     zp_mos_INT_A                    ; 0E50 A5 FC                    ..
        pha                                     ; 0E52 48                       H
        txa                                     ; 0E53 8A                       .
        pha                                     ; 0E54 48                       H
L0E55:  tya                                     ; 0E55 98                       .
        pha                                     ; 0E56 48                       H
        lda     $0CFA                           ; 0E57 AD FA 0C                 ...
        beq     L0E61                           ; 0E5A F0 05                    ..
        ldx     #$81                            ; 0E5C A2 81                    ..
        jsr     OSBYTE                          ; 0E5E 20 F4 FF                  ..
L0E61:  lda     sheila_SYSVIA_ifr               ; 0E61 AD 4D FE                 .M.
        pha                                     ; 0E64 48                       H
        lda     #$10                            ; 0E65 A9 10                    ..
        pha                                     ; 0E67 48                       H
        lda     #$C0                            ; 0E68 A9 C0                    ..
        pha                                     ; 0E6A 48                       H
        php                                     ; 0E6B 08                       .
        jmp     (L008A)                         ; 0E6C 6C 8A 00                 l..
[Part of the AMPLE interrupt handler, which calls OSBYTE!]
[/quote]
Ooo, dangerous. What would happen if that interupt happened in the middle of an OSBYTE/OSWORD call? EF/F0/F1 would be whipped away under its feet. While the OSBYTE/OSWORD dispatcher disables interupts, picture what would happen if a call called something that enabled interupts. eg: loop:JSR something:STA (F0),Y:INY:Bxx loop. Any non-ROM-based OSWORD handler, such as disk-based OSWORD 64 *MOUSE handlers.

I suspect that what is happened up there is that earlier on something is checking to make sure that this interupt will not happen in the middle of an OSBYTE. Or, it's flying by the seat of its pants and just happens to have not seen any problems.
dominicbeesley wrote:
Wed Jul 10, 2019 9:49 am
So it seems your assertion
However, you are safe to enable interupts during your code, as interupts aren't allowed to mess with &EF/F0/F1 as they are foreground workspace.
is not quite true. Your rules aren't followed by other applications and so I can't re-enable interrupts and use EF/F0/F1 if I want my code to work with Ample.
...
So I think to make my ROM more likely to work it can't rely on F0/F1 while interrupts are enabled and needs to save / restore for safety, which is a faff but not a show stopper as I'm only going to be re-enabling interrupts.
Safe "just in case" programming, backed up with knowledge that this specific application bends the rules. I've had to code stuff that had to work around other calls trashing stuff it wasn't supposed to. OSWORD &7F is a particular culprit - god, the belts and braces I've had to put around OWORD &7F calls* - but OSWORD 14 on the Master Compact bit me hard - I had to code HADFS to specifically check for MOS 5 and specifically avoid calling the MOS to get the date.

*DFS 0.90 translates **ALL** calls >&7E into OSWORD &7F, which kills the ability to call OSWORD &B0 to access MMC data. And DFS 0.90 doesn't implement service call 18 to test for its presence, so you can't test that it's there and work around it.

Code: Select all

$ bbcbasic
PDP11 BBC BASIC IV Version 0.25
(C) Copyright J.G.Harston 1989,2005-2015
>_

User avatar
jgharston
Posts: 3596
Joined: Thu Sep 24, 2009 11:22 am
Location: Whitby/Sheffield
Contact:

Re: uknown osword handler in service rom

Post by jgharston » Sun Jul 14, 2019 1:28 pm

dominicbeesley wrote:
Sun Jul 14, 2019 7:43 am
So has anyone else seen examples of testing v after a call to osbyte? Is it a valid way to test for the presence of a rom?
The valid way to test for a sideways ROM OSBYTE call is to test for X=&FF on return. The definitive specification of what you can can rely on to be returned from a MOS call is the Tube API. If the Tube API does not pass the the data it "legally" does not exist. The Tube API specifies that OSBYTE<&80 X is returned, OSBYTE>&7F, X,Y,Cy is returned. You MUST NOT rely on ANYTHING else.

LDA #call number:JSR OSBYTE
INX:BEQ nobody_responded

Code: Select all

$ bbcbasic
PDP11 BBC BASIC IV Version 0.25
(C) Copyright J.G.Harston 1989,2005-2015
>_

dominicbeesley
Posts: 799
Joined: Tue Apr 30, 2013 11:16 am
Contact:

Re: uknown osword handler in service rom

Post by dominicbeesley » Sun Jul 14, 2019 4:13 pm

Thanks for the answers
jgharston wrote:
Sun Jul 14, 2019 1:23 pm
Ooo, dangerous. What would happen if that interupt happened in the middle of an OSBYTE/OSWORD call? EF/F0/F1 would be whipped away under its feet. While the OSBYTE/OSWORD dispatcher disables interupts, picture what would happen if a call called something that enabled interupts. eg: loop:JSR something:STA (F0),Y:INY:Bxx loop.

My point exactly but it seems that this does happen so if I need to enable interrupts in my OSWORD I will preserve F0 (it's not a big deal, if I'm enabling interrupts its because I'm slow a few cycles pushing an popping is no biggy
jgharston wrote:
Sun Jul 14, 2019 1:23 pm
I suspect that what is happened up there is that earlier on something is checking to make sure that this interupt will not happen in the middle of an OSBYTE. Or, it's flying by the seat of its pants and just happens to have not seen any problems.
I didn't get that far with the disassembly but it looks to me like that is before any checking!

You mention the tube spec - I'm not sure which spec though. Is it on mdfs.net somewhere?

D

User avatar
jgharston
Posts: 3596
Joined: Thu Sep 24, 2009 11:22 am
Location: Whitby/Sheffield
Contact:

Re: uknown osword handler in service rom

Post by jgharston » Mon Jul 15, 2019 1:29 am

I've checked through the code for the BBC and Master MOS.

All code is written to assume that it owns &F0/&F1 and nothing is going to change it in the background - but all such code is called via the OSBYTE/OSWORD dispatcher with disables interupts, so the code assumes it is running with interupts disabled.

I have found three exceptions, all on the Master.

OSBYTE 20/25 font reset uses the interupt workspace at &FA/&FB and disables interupts before using it to prevent IRQs using it. However, OSBYTEs are run with IRQs disabled, so there may be a path to the OSBYTE 20/25 code that gets there with IRQs enabled.

Similarly, a bit of the VDU driver also disables IRQs to use &FA/&FB, but that's understandable as the VDU driver is run in the foreground. OSBYTE 20/25 could be disabling IRQs because it's part of the VDU code.

OSWORD 14 to read the RTC saves &F0/&F1 and then temporarily enables IRQs with a CLI:SEI sequence to let any pending IRQs through while it is waiting for the RTC hardware to be ready to read. So it is written on the assumption that somebody hanging on interupts could mess with &F0/&F1 and not restore them.


So, for defensive programming the following is probably appropriate:

A sideways ROM OSBYTE/OSWORD handler will have IRQs disabled, so nobody will mess with &F0/&F1 while your code is running as long as you keep IRQs disabled, and usefully also &FA/&FB.

If you need to enable IRQs assume you lose control of &F0/&F1 and save/restore them around your IRQ-enabled code. Also, while IRQs are enabled, &FA/&FB will be being used by IRQ handlers.

You also lose &FA/&FB if you call any of the buffer vectors, as they are used to index into the buffers - that is the main use of them by interupts.

And, naturally, if your handler calls OSWORD/OSBYTE then &F0/&F1 will get set to whatever is appropriate for that call, so your handler should set &F0/&F1 back to what it appropriate for itself.

An OSBYTE/OSWORD handler called by intercepting the vectors (such as going via an extended vector into a sideways ROM) is run with IRQs *enabled*, so your code must assume that it can't use &FA/&FB and should assume that &F0/&F1 may changed by un-neighbourly code.

In light of that I'm in two minds as to whether to be neighbourly you should write interupt code to ensure that you leave &F0/&F1 in their previous state, as all examined code that enables IRQs assumes that results in &F0/&F1 being trashed!

(I've read the above a few times, I'm fairly sure I've got the 'not's and 'do's all the right way around!)

Code: Select all

$ bbcbasic
PDP11 BBC BASIC IV Version 0.25
(C) Copyright J.G.Harston 1989,2005-2015
>_

User avatar
jgharston
Posts: 3596
Joined: Thu Sep 24, 2009 11:22 am
Location: Whitby/Sheffield
Contact:

Re: uknown osword handler in service rom

Post by jgharston » Mon Jul 15, 2019 1:30 am

dominicbeesley wrote:
Sun Jul 14, 2019 4:13 pm
You mention the tube spec - I'm not sure which spec though. Is it on mdfs.net somewhere?
http://mdfs.net/Software/Tube/Docs/Protocol

Code: Select all

$ bbcbasic
PDP11 BBC BASIC IV Version 0.25
(C) Copyright J.G.Harston 1989,2005-2015
>_

dominicbeesley
Posts: 799
Joined: Tue Apr 30, 2013 11:16 am
Contact:

Re: uknown osword handler in service rom

Post by dominicbeesley » Mon Jul 15, 2019 8:55 am

Thanks JGH, that's where I'd got to on OBYTE/WORD - good call on FA/FB too!

Where did you get the information for the tube document from did you reverse engineer it or was there an official Acorn document. I've never found one, I spent some time looking when looking at making a block/network-friendly serial tube protocol.

Ta

D

Post Reply