George, there are multiple ways to do this, which I have been doing a deep dive on recently for my "Supercharged BASIC" book in progress. Some background first, but stay till the end, I have what should be a perfect solution for you.
First, there is the RELJMP.PDF that you may or may not have. Attached. You need a 4 byte hidey hole. Probably somewhere in the RST 7 table would work. Clobbers HL, DE, flags. Can do conditional/unconditional jumps. It's a a "Call" in form but really it's a relative jump. You cannot use it directly to do a subroutine. I think the real downside here is all the pushing and popping. Imagine a loop that just copies bytes from one place to another. You probably need HL and DE, plus the flags preserved across the jump, minimum. So you're going to have to do all that. Every jump. Second, at 12777 in the Model 100 is the code XTHL / PCHL. This code simply answers the question "Where Am I?" You can use this as a building block to do a relative jump. Steve Adolph and I went down this rabbit hole and it seems pretty expensive at least if you preserve registers. But it also works. What came up from this collaboration is what I think is the perfect technology for more BASIC embedded ML that requires branching. By the way, there's a lot you can do to augment BASIC code without branching. If you can, short sequential routines that optimize your code is the way to go. Anyway, the perfect solution... basically this idea is a 2-byte relative branch or call encoded as data following a RST 7 / 197 instruction: RST 7 / .db 197 / opcode / signed 8-bit offset In the RST 7 / .db 197 table we put a small routine that rewrites the whole 4 bytes as your opcode,the 8-bit signed offset converted to a fixed address relative to the final position of the opcode, followed by a NOP. opcode / 2-byte target / nop Advantages? You can do jumps, calls, conditionals no limitations on the opcode. It's fast, there's overhead the first time to rewrite the jump, but after that it's at max speed, every iteration. Well, other than the NOP that pads out to the 4 bytes. Disadvantages: it rewrites code. You cannot use this in literal strings since it will corrupt your tokenized program text with control characters, " and DEL. But all characters are allowed in dynamic strings... So A$="BLAH" is no but A$="BLAH"+"" is OK. It might not be the best tech for a single branch. RELJMP, or CALL 12777 may be best. But if you're looping over data, I think you're going to win this way. I've attached a sample program with the RST7 self-relocator installer and a test program that shows BASIC-only versus an ML CALL subroutine to print the full M100 character set. The CALL string program does this: mvi a,33 rst 4 inr a rz mvi h,126 inr h cmp h rst 7 / .db 197 / .db jz / .db -5 rst 7 /.db 197 / .db jmp / .db -11 My self-relocator installer source... note that this is specially crafted code that is embedded in a BASIC literal string, so it doesn't use the full 8085 instruction set. This means I can write it in a string without any conversions, special construction +CHR$( or POKEs. If you list SRELC2.BA you will see what I mean. rst 7 / index / rel-offset / opcode gets replaced with opcode / address / nop ; store FIXUP @ ERRLIN (64415) - "hook 99" = postbyte 197 ; Use CALL to the start of the string. ; HL contains the address of the string body push h lxi h,64415 xthl ; stack the hook slot for later, hl gets the installer base mvi a,-18 ; calculate the address of the rst 7 handler based on length of installer cma mov e,a xra a mov d,a call 0x21AC ; dad d / ret ; now hl has the rst 7 handler to install pop d ; get back the 64415 slot address shli ; store the vector ret 21 bytes rst 7 ndx opcode rel-offset xthl ; save-hl, hl gets the return address (points at opcode) push psw push d xchg lhli ; fetch opcode & rel-offset to hl xchg ; now opcode & rel-offset in de dcx h ; now pointing where the jump target goes push h ; save the jump-target position dcx h ; hl points at start of instruction mov m,e ; place jump/call opcode mov a,d ; sign extend the 8-bit offset mov e,a add a sbb a ; mov d,a ; de now has sign-extended offset mov a,e ; dad d: hl = hl + de... now has the computed jump target call 0x21AC ; main rom has DAD D/ RET. We need it since DAD D too low for literal string pop d ; retrieve the jump target position shli ; instruction is complete, except for the NUL xchg ; back into h inx h inx h xra a ; nop code mov m,a ; set nop dcx h ; at nop, so 3 decrements to again point at opcode dcx h dcx h pop d ; restore caller's de pop psw ; restore caller's psw xthl ; stack the patched-up instruction, restore caller's hl ret ; invoke the patched-in jump/call -- John. On Tue, Mar 7, 2023 at 4:45 AM grima...@gmail.com <grima...@gmail.com> wrote: > Hi all, > > One of the things I struggled with in trying to build 8085 subroutines for > BASIC program was the lack of a relative jump command. > > So far, the approach I have taken to embed ML programs into BASIC has been > to poke them into arrays, thus allowing BASIC to manage the routines within > memory. However, I then have to use BASIC to get VARPTR of the array and > update all JMP locations before calling the subroutine, just in case BASIC > has moved the array. > > The other thought I had was, can I have the ML program modify itself when > it runs? I was racking my brain reading the Inten 8085 documentation, and > as far as I can tell there is no easy way to read the program counter into > any of the register pairs, which I would want to do in order to calculate > offsets and update JMP locations. > > However I had one thought. It seems that both CALL and RST instructions > push the program counter onto the stack. Is it possible to leverage either > of these and then RET to return to my program, and then immediately > decrement the stack pointer and to retrieve the previous value. > > Then I can use that value to calculate all the offsets and update the JMP > locations. > > Does anyone have any constructive input here? > > -George >
RelJMP.pdf
Description: Adobe PDF document
SRELC2.BA
Description: Binary data
SRELC2.DO
Description: Binary data