• Merlin32 and Negative DS Pseudo Op

    From Hugh Hood@21:1/5 to All on Sun Oct 10 13:50:41 2021
    I'm doing some continually updated patches to an existing binary file
    (ProDOS - 8 bit) where I use the Merlin32 'PUTBIN' pseudo op to place
    the existing binary at the current object pointer, add my new code to
    the end, and then assemble the source to generate the patched binary.
    Simple enough.

    For example:

    Start
    PUTBIN FILETOPATCH ; existing binary file

    NewCode
    LDA {etc} ; all the new and patching code

    CodeEnd
    SAV PATCHEDFILE ;


    I've been manually editing the first three (3) bytes of the existing
    binary so that its first instruction is to JMP to NewCode. That's not
    very difficult nor time consuming, but I'd like to make it all more
    automatic, if possible.

    Ideally, I would use a Pseudo Op at the end of the source code to move
    back the object pointer to the very beginning and overwrite the first
    three (3) bytes of the PUTBIN'ed file with the necessary JMP to NewCode.

    The Merlin 16 manual mentions using the 'DS' pseudo op with a negative
    number (e.g. DS-1) to "back up the object and address pointers".
    Frankly, I'm not sure if even that would accomplish what I'd like, but I
    do know that in Merlin32 1.0 using 'DS-1' just generates an 'UNKNOWN' error.

    Can anyone set me on the straight path to some method that would work?

    I'll even gladly accept 'no, that can't be done' so that I won't spend
    any more time on it, and just keep manually patching those first three
    (3) bytes.

    Thanks.




    Hugh Hood

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Antoine Vignau@21:1/5 to All on Fri Oct 22 11:37:39 2021
    Hi Hugh,
    I do not understand what you want to achieve with the negative DS.
    On Merlin 16 and 32, DS -1 will reserve $65535 bytes of memory.
    On Merlin 16 and 32, DS *-1 will reserve current_address - 1 bytes of memory.

    What am I missing here? If you want to link to an address in the putbin, you can do the following:

    myCode putbin toto.bin
    myLabel = *

    patchAbove
    lda #$BD
    sta myLabel-3

    Cheers,
    Antoine

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From fadden@21:1/5 to All on Sat Oct 23 08:03:45 2021
    I believe what he's trying to do is patch the binary included with PUTBIN with the assembler itself.

    With an assembler written by C64 people you can do this, because they have separate notions of "physical" and "logical" program counters within the assembler. For example, in 64tass if you do this:

    * = $1000
    lda $1234

    * = $1001
    .word $4567
    rts

    The output is:

    00000000: ad67 4560 .gE`

    Merlin32 only has a "logical" PC, so it assembles the same code to:

    00000000: ad34 1267 4560 .4.gE`

    The C64 assemblers place everything into a 64KB bank. If the output is discontiguous, you'll get empty gaps in the output file. It will even wrap around at the end of the bank, so the stuff you output at the end of the source file ends up at the start
    of the binary. (https://sourceforge.net/p/tass64/bugs/59/)

    Once I understood this, certain aspects of 64tass and ACME made a lot more sense. I'm not aware of an Apple II assembler that had the notion of separate PCs, though the old "OBJ" directive could have been used this way.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kent Dickey@21:1/5 to fadden@fadden.com on Sat Oct 23 11:17:35 2021
    In article <e4fe03ff-6504-4557-8408-c7275de5e1a4n@googlegroups.com>,
    fadden <fadden@fadden.com> wrote:
    I believe what he's trying to do is patch the binary included with
    PUTBIN with the assembler itself.

    With an assembler written by C64 people you can do this, because they
    have separate notions of "physical" and "logical" program counters
    within the assembler. For example, in 64tass if you do this:

    * = $1000
    lda $1234

    * = $1001
    .word $4567
    rts

    The output is:

    00000000: ad67 4560 .gE`

    Merlin32 only has a "logical" PC, so it assembles the same code to:

    00000000: ad34 1267 4560 .4.gE`

    The C64 assemblers place everything into a 64KB bank. If the output is >discontiguous, you'll get empty gaps in the output file. It will even
    wrap around at the end of the bank, so the stuff you output at the end
    of the source file ends up at the start of the binary. >(https://sourceforge.net/p/tass64/bugs/59/)

    Once I understood this, certain aspects of 64tass and ACME made a lot
    more sense. I'm not aware of an Apple II assembler that had the notion
    of separate PCs, though the old "OBJ" directive could have been used
    this way.

    EDASM worked differently and I think you could rewrite earlier
    instructions by storing instructions directly in memory at the OBJ
    addresses. EDASM was really slow and hard to use, so it wasn't popular
    (at least the DOS 3.3 version was slow).

    Kent

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From fadden@21:1/5 to Kent Dickey on Sat Oct 23 10:17:35 2021
    On Saturday, October 23, 2021 at 9:17:41 AM UTC-7, Kent Dickey wrote:
    EDASM worked differently and I think you could rewrite earlier
    instructions by storing instructions directly in memory at the OBJ addresses. EDASM was really slow and hard to use, so it wasn't popular
    (at least the DOS 3.3 version was slow).

    From the "Apple 6502 Assembler/Editor" manual (the scan of which doesn't seem to include a page with a copyright date on it):

    "The OBJ directive has been included for compatibility with a previous version of this Assembler, in which it was used to specify the memory address of the output object file, which now can only be written on the output diskette. This directive is
    reserved for possible future enhancement of the Assembler/Editor system."

    So I think the DOS Toolkit version of EDASM didn't really support it either.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hugh Hood@21:1/5 to fadden on Sat Oct 23 13:43:46 2021
    On 10/23/2021 10:03 AM, fadden wrote:


    I believe what he's trying to do is patch the binary included with
    PUTBIN with the assembler itself.


    Exactly! Thanks for boiling that down to one succinct sentence for me.

    Thanks, fellas, for chiming in with the information and your thoughts
    about this. I don't mind patching the object code after the assembler
    generates it, but I didn't want to overlook an easier way to do it all
    from within the assembler.

    I've seen many clever techniques using assembler math and '*' operations
    here and thought I'd give it a shot. Thanks.




    Hugh Hood

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Oliver Schmidt@21:1/5 to All on Sun Oct 24 08:23:41 2021
    Hi Hugh,

    I believe what he's trying to do is patch the binary included with
    PUTBIN with the assembler itself.

    Exactly! Thanks for boiling that down to one succinct sentence for me.

    The ld65 linker supports 'overwrite' segments for that very purpose. https://cc65.github.io/doc/ld65.html#ss5.4 says:

    Perhaps you are modifying an OS ROM that has its public subroutines at
    fixed, well-known addresses, and you want to prevent them from shifting to other locations in memory if your changed code takes less space. Or you are updating a block of code available in binary-only form with fixes that are scattered in various places. Generally, whenever you want to minimize disturbance to an existing code brought on by your updates, OVERWRITE
    segments are worth considering.

    Regards,
    Oliver

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)