Modifying interrupt address
Modifying interrupt address
Hi,
I was wondering, is it safe or useless, when writing code to change the IRQ vector (in $245-$246 on the Atmos), to disable interrupts first ?
Is there any risk that an interrupt could happen let's say when only one of the two bytes have been changed, thus leading to some random jump?
I would do that but for instance the classical clock program in Théoric magazine (issue 6) doesn't.
I was wondering, is it safe or useless, when writing code to change the IRQ vector (in $245-$246 on the Atmos), to disable interrupts first ?
Is there any risk that an interrupt could happen let's say when only one of the two bytes have been changed, thus leading to some random jump?
I would do that but for instance the classical clock program in Théoric magazine (issue 6) doesn't.
Re: Modifying interrupt address
245-246 is indeed the IRQ vector, but the code in Theoric does not change that, instead it patches the data at 24A/24B/24C.
It first writes the address 9500 to 24B/24C, then it replaced the RTI located in 24A by a JMP.
So yes, the way it's done is safe, as long as the RTI is modified last
And when restoring, you need to put the RTI first.
It first writes the address 9500 to 24B/24C, then it replaced the RTI located in 24A by a JMP.
So yes, the way it's done is safe, as long as the RTI is modified last
And when restoring, you need to put the RTI first.
Re: Modifying interrupt address
Definitely NO! It's not safe nor useless until as Dbug said there is a RTI at #244.
Using BASIC for this task:
Code: Select all
10 POKE#245,LO:POKE#246,HI
Code: Select all
10 DOKE#245,HILO
Code: Select all
LDX #LO
LDY #HI
STX $245
STY $246
So, use SEI/CLI, Luke! Or depending on the whole program structure use PHP+SEI/PLP - I'm using this in my custom Oric library functions (sound players, keyboard handlers, etc.), so on the price of 3 bytes I have always working code .
Easy alternatives are:
- put first a RTI at #244 then do whatever you want;
- disable VIA interrupts (POKE#30E,#7F) but this will work of course only in case no other IRQ sources are attached (i.e. no FDC, RS232 etc. are connected).
Re: Modifying interrupt address
Thanks for the replies! What did I ask
Well spotted Dbug by the way.
ISS that's funny, I think long ago I tried in Basic but quickly figured that it couldn't work
Well spotted Dbug by the way.
ISS that's funny, I think long ago I tried in Basic but quickly figured that it couldn't work
Re: Modifying interrupt address
So I made my small program, whose goal is to constantly display the value of a byte on screen with interrupts. The goal for instance is to check what's hapening on page 3 with a hardware device.
It's running fine but crashed with the LIST command. I tried to check what's happenning, and apparently when crashed the LIST command is stuck into a "key press" check. I'm puzzled, it's like a RTS goes back to the same calling address and not after. Same with Euphoric.
Anyone ever encountered something like this ?
I suspect I did something wrong somewhere.
Attached: program and listing
It's running fine but crashed with the LIST command. I tried to check what's happenning, and apparently when crashed the LIST command is stuck into a "key press" check. I'm puzzled, it's like a RTS goes back to the same calling address and not after. Same with Euphoric.
Anyone ever encountered something like this ?
I suspect I did something wrong somewhere.
Attached: program and listing
Re: Modifying interrupt address
Not sure what's wrong, but a couple of notes:
Don't write JSR+RTS
just write JMP
When changing stuff like CPU flags in an IRQ, don't use CLI or CLD to restore, because you don't know what the original value was, instead of
Prefer
If for some reason LIST was using BCD mode, you restore what it was expecting, else you break the code when it comes back.
Don't write JSR+RTS
Code: Select all
0100 20 42 01 JSR $0142 JSR to set the interrupt. Doing so allows the code being crushed by the stack later
0103 60 RTS
Code: Select all
0100 20 42 01 JMP $0142 JSR to set the interrupt. Doing so allows the code being crushed by the stack later
Code: Select all
SED
...
CLD
Code: Select all
PHP
SED
...
PLP
Re: Modifying interrupt address
This was easy!
BASIC uses $100..$10A as buffer to convert float point numbers to string.
So LIST and (probably) everything else which converts fp-numbers will hang (for instance PRINT 1+1).
I suggest to move your code at $110 - it seams it'll be safe!
Or (as in attached file) move the initialization routine at top (i.e. $100).
The attached file contains converted asm-source to XA and compiled test.tap file.
To compile use:
Code: Select all
xa -C -W -o test -bt 256 Display_Byte_ASM_source.s
header -a1 -h1 -b1 test test.tap 256
EDIT2: Nice arithmetic trick BASIC versions 1.0/1.1!
- Attachments
-
- DisplayByte-fix.zip
- (1.82 KiB) Downloaded 122 times
Re: Modifying interrupt address
Ouch, thanks a lot for the fast analysis! I stupidly checked the top of the stack, but not the start of page 1. Mmmmh, should stick to page 4 for my tests, before trying to find smart areas to set my code without knowing the Oric interpreter well enough.
Thanks again, will check your version
Thanks, it's a re-use of Novalight code where I sometimes went into another dimension to find how to save a few bytesEDIT2: Nice arithmetic trick BASIC versions 1.0/1.1!
Re: Modifying interrupt address
Also, I've to say, looking at this type of code that does not use an actual assembler source code we can just reassemble is super frustrating, specially because the code is not standardized:
vs
In 6502 assembler the presence of the # is super important:
#$04 means "immediate value 4"
$04 mean "memory location 4 in zero page"
Code: Select all
0146 A9 04 LDA #$04 | redirectinq IRQ
014B A9 01 LDA #$01 | ROM1.0: 229-22A ; ROM 1.1: 245-246 (which is $229 + $1C)
Code: Select all
010C 29 0F AND $0F Keep only the 4 low bits (=> 2nd digit)
010E C9 0A CMP $0A A - #0A: C=1 if no carry is needed (so if A is between 0A and 0F)
0110 69 30 ADC $30 Add 48 to get the ASCII code. Carry (+1) and BCD mode (+6) will be added
#$04 means "immediate value 4"
$04 mean "memory location 4 in zero page"
Re: Modifying interrupt address
Ah yes sorry, I've been copying/pasting parts of code when I didn't use the right $# use at the time. I got an excuse though: currently fighting Omicron and trying to keep me busy with very, very short nights
Re: Modifying interrupt address
Thanks, I think the worst is behind me (there was nothing serious but it knocked me down because of the lack of sleep).
Anyway I have in mind a kind of Excel table to write my code, which would let me present the "listing" the way I like (addresses / execution time, etc.) and save me time when I'm toying with addresses, and let me generate somthing that looks more like a standard source code. Haven't worked on it but should be doable.
You guys are going to tell me "why on earth don't you learn ASM properly", I know Reason is I really got trouble not seeing clearly which op code (thus addressing mode) is behind the instructions.
Thanks for the help guys
Re: Modifying interrupt address
You can still do something hybrid:
- Put your source code in a .S file that compiles with XA (you don't even need the OSDK, you can call directly XA and output to a .BIN file if you want)
- Put comments on the right side with your opcodes
- Use Oricutron debugger cycle counter display (the CY value which you can reset with F9)
0100 20 42 01 JMP $0142 JSR to set the interrupt. Doing so allows the code being crushed by the stack later
*=$100
JMP $0142 ; 20 42 01 JSR to set the interrupt. Doing so allows the code being crushed by the stack later