Jump to content
IGNORED

Assembler variable subroutines


Recommended Posts

Variable subroutines,I wonder if this is something that is common in mac65 assembler, And how its done, to show what i mean heres a example in Basic:

 

50 Gosub X

 

So it will gosub the value that is stored in X, the value in X can be changed when needed so that the subroutine can reach different places in the program from the same line 50 Gosub X.

 

How is this done in assembler ? and it is a normal practis to use this kind of feature ?

 

Maybe it something like this ?

 

JSR VARIABLE

 

So it will JSR whatever value is in the VARIABLE Equate ?

 

but then how to change that Varable ? Do i need the exact memory adress for the program line to put in the VARIABLE Equate ?

 

The Atasm compiler shows the memory adresses for the program lines, but when editing the assembler program these adresses can easily change making this very cumbersome when programming.

 

 

 

 

 

 

Link to comment
Share on other sites

Common method is to push the subroutine address minus one (MSB first) onto the stack then RTS. You can have a look up table of addresses and index them with the X or Y registers depending on some condition.

 

LDX INDEX

LDA ADDRESSHI,X

PHA

LDA ADDRESSLO,X

PHA

RTS

 

...

 

ADDRESSLO

.BYTE <ADDR1-1, <ADDR2-1, ...

 

ADDRESSLO

.BYTE >ADDR1-1, >ADDR2-1, ...

Link to comment
Share on other sites

Another method is using indirect jump:

  lda tabl,x
  sta jpad
  lda tabh,x
  sta jpad+1
  jmp (jpad)

tabl:
  .byte <proc1
  .byte <proc2

tabh:
  .byte >proc1
  .byte >proc2

or selfmodifying code:

  lda tabl,x
  sta jpad
  lda tabh,x
  sta jpad+1
jpad = *+1
  jmp $ffff

The last one must be placed in RAM of course.

  • Like 1
Link to comment
Share on other sites

They forgot to put a JSR(ind) instruction into the original 6502 design.

 

So you have to implement it as previously illustrated. The pushing <address - 1> onto the stack method has the advantage of not needing you to reserve the temporary vector in memory.

Of course another alternate could be to use self-modifying code so rather than maintain a vector you just alter the operand of a JMP instruction.

 

For either method, it's probably a good idea to do bounds checking on the parameter just to make sure you don't jump to some random location.

Edited by Rybags
Link to comment
Share on other sites

Thank you. I think the indirect jump is easiest for me to understand. So it can use JSR (JPAD) instead of JMP (JPAD) ? should work equally well ?

As they wrote earlier - there is no jsr (ind), but in self-modifying code you can use jsr $ffff.

Link to comment
Share on other sites

  • 2 weeks later...

As far as I know, there is no way to get to the built-in relocatable handler on the 1200XL or 800XL OS as it has no public vector and is invoked only by the SIO-based loader. The only way you can get to it is by creating an SIO device that can push such a handler or emulating one through a PBI device. I don't know if any exist; the only way I was able to test my own implementation was to create an emulated device for it in Altirra. On top of that, the peripheral handler loader is one of the first things people rip out when they're looking for space in the OS ROM, and it uses a weird format that no assembler generates. I don't recommend trying to use it.

 

If you want to make your own relocatable executable, it's easiest to either use a toolchain already set up to generate them and with a relocator already written (ca65/ld65), or assemble your executable twice at two different addresses and generate only high-byte relocations. Relocating only by whole page avoids a lot of headaches; it's easier to generate, easier to relocate, and you don't have to worry about JMP (abs) blowing up because MEMLO happened to be at an odd address.

  • Like 2
Link to comment
Share on other sites

It seems to me that I asked a question not clearly enough... :_(

 

I'm learning MAE macroassembler now and found in manual .MC adr pseudo-operator

.MC adr
Move Code to a different address than the .OR assembly origin. If you are assembling to RAM, your code will be stored starting at the address after the .MC pseudo-op.

When assembling to disk, the .MC address will be used when creating the binary file headers, affecting where the code will be loaded into.

 

Then I've thought about the ability to extract memlo data while assembling by means of assembler itself and use this data as an address part of .MC pseudo-op before runtime period.

 

Another sorry for my Google translator :-D

Link to comment
Share on other sites

Since you can't know what MEMLO will be when the program is run, you might as well pick a safe load address (e.g. $2000) use that as the origin (".OR"). Loading code at a different address to the run address is useful mainly when it's not possible to load code at the address it will execute. For example, TBXL has code segments which load in RAM (at the ".MC" address) and are moved under the OS before execution (at the ".OR" address). But in that case, both addresses are known at compile time and will not change at run time.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...