Modifying interrupt address

Here you can ask questions or provide insights about how to use efficiently 6502 assembly code on the Oric.
User avatar
Symoon
Archivist
Posts: 2307
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

Modifying interrupt address

Post by Symoon »

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.
User avatar
Dbug
Site Admin
Posts: 4444
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: Modifying interrupt address

Post by Dbug »

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.
User avatar
iss
Wing Commander
Posts: 1641
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

Re: Modifying interrupt address

Post by iss »

Symoon wrote: Tue Feb 15, 2022 9:49 amI was wondering, is it safe or useless...
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
is crazy, even:

Code: Select all

10 DOKE#245,HILO
is gambling, even more, the fastest ASSEMBLER code to hook the IRQ:

Code: Select all

    LDX #LO
    LDY #HI
    STX $245
    STY $246
exposes 4 cycles risky time :).
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).
User avatar
Symoon
Archivist
Posts: 2307
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

Re: Modifying interrupt address

Post by Symoon »

Thanks for the replies! What did I ask :lol:
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 ;)
User avatar
Symoon
Archivist
Posts: 2307
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

Re: Modifying interrupt address

Post by Symoon »

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
Display_byte.zip
(1.71 KiB) Downloaded 149 times
User avatar
Dbug
Site Admin
Posts: 4444
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: Modifying interrupt address

Post by Dbug »

Not sure what's wrong, but a couple of notes:

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
just write JMP

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
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

Code: Select all

SED
...
CLD
Prefer

Code: Select all

PHP
SED
...
PLP
If for some reason LIST was using BCD mode, you restore what it was expecting, else you break the code when it comes back.
User avatar
iss
Wing Commander
Posts: 1641
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

Re: Modifying interrupt address

Post by iss »

Symoon wrote: Wed Feb 16, 2022 8:16 amAnyone ever encountered something like this ?
This was easy! :D
Screenshot_20220216_102322.png
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
EDIT: In the attached source is used PHP/PLP exactly as Dbug said! :twisted:
EDIT2: Nice arithmetic trick BASIC versions 1.0/1.1! :wink:
Attachments
DisplayByte-fix.zip
(1.82 KiB) Downloaded 122 times
User avatar
Symoon
Archivist
Posts: 2307
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

Re: Modifying interrupt address

Post by Symoon »

iss wrote: Wed Feb 16, 2022 9:54 am This was easy! :D
BASIC uses $100..$10A as buffer to convert float point numbers to string.
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 :)
EDIT2: Nice arithmetic trick BASIC versions 1.0/1.1!
Thanks, it's a re-use of Novalight code where I sometimes went into another dimension to find how to save a few bytes :lol:
User avatar
Dbug
Site Admin
Posts: 4444
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: Modifying interrupt address

Post by Dbug »

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:

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)
vs

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
In 6502 assembler the presence of the # is super important:
#$04 means "immediate value 4"
$04 mean "memory location 4 in zero page"
User avatar
Symoon
Archivist
Posts: 2307
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

Re: Modifying interrupt address

Post by Symoon »

Dbug wrote: Wed Feb 16, 2022 10:18 am 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
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 ;)
User avatar
iss
Wing Commander
Posts: 1641
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

Re: Modifying interrupt address

Post by iss »

Symoon wrote: Wed Feb 16, 2022 10:24 am...fighting...
Keep going and quick recovery!
Your unique coding way is a super fitness for the mind and the body and will help!
User avatar
Symoon
Archivist
Posts: 2307
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

Re: Modifying interrupt address

Post by Symoon »

iss wrote: Wed Feb 16, 2022 10:31 am Keep going and quick recovery!
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 ;)
User avatar
Dbug
Site Admin
Posts: 4444
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: Modifying interrupt address

Post by Dbug »

Symoon wrote: Wed Feb 16, 2022 10:41 am 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.
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
User avatar
Symoon
Archivist
Posts: 2307
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

Re: Modifying interrupt address

Post by Symoon »

iss wrote: Wed Feb 16, 2022 9:54 am EDIT: In the attached source is used PHP/PLP exactly as Dbug said! :twisted:
I was about to say you could save a PLP by doing it earlier...
But heh, got it, I'm still tired I guess :lol:
Post Reply