Oops, put an old version of SRELC2.DO, here's the one that matches the BA.

On Tue, Mar 7, 2023 at 10:43 AM John R. Hogerhuis <jho...@pobox.com> wrote:

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

Attachment: SRELC2.DO
Description: Binary data

Reply via email to