Relatively easy

By NYYRIKKI

Enlighted (5421)

NYYRIKKI's picture

16-01-2011, 16:40

Every now and then you end up to situation where you need to make relocatable code. Normally the best thing to do is to generate relocate tables and apply them on top of code. This is the method that is used for example in SymbOS. Unfortunately assemblers very rarely support making these relocate tables. Here is anyway one example how to make them your self:

http://www.msx.fi/nyyrikki/files/freepos.lzh

Sometimes it would be anyway nice to have some small code that you can for example drop from memorymapper to any RAM area and call immediately. Here is example of one way, how you can do that. Bad thing in this method is that it slows down the execution and therefore it should be used only in cases when code is not speed critical. On the good side is that you can skip the time taking task messing up with tables.

Macro implementations may differ a bit from assembler to another, but this example has been tested with sjasm v0.42b8

If you place the "R" (relative) in front of wrong command, the program will still work, but it will cause more useless delay. (In sjasm v0.42b8 you can detect this kind of failure from weird note in output: "from macro R line xx")

I hope this example helps some of you...


        ORG #100

        ; You can use any address here
        LD     DE,#C000

        ; Move code to DE and start it.

        PUSH   DE
        LD     HL,Relative_code_start
        LD     BC,Relative_code_end - Relative_code_start
        LDIR
        RET

;------------------------------------------------------------
; Macro to keep readibility in rest of the source

        MACRO R CMD+
        CALL Next_is_relative3 - ((.end-.beg)>3)*(Next_is_relative4-Next_is_relative3)+((.end-.beg)<3 or (.end-.beg)>4)
.beg:   CMD -$-2
.end:
        ENDMACRO


; Macro support routines (must be in fixed address)

        RET             ; This is here in case you put 'R' in front of wrong command.
Next_is_relative3:

        EX     (SP),HL
        PUSH   DE
        PUSH   AF
        INC    HL
        LD     E,(HL)
        INC    HL
        LD     D,(HL)
        EX     DE,HL
        ADD    HL,DE
        EX     DE,HL
        LD     (HL),D
        DEC    HL
        LD     (HL),E
        DEC    HL
        POP    AF
        POP    DE
        EX     (SP),HL
        RET

Next_is_relative4:

        EX     (SP),HL
        PUSH   DE
        PUSH   AF
        INC    HL
        INC    HL
        LD     E,(HL)
        INC    HL
        LD     D,(HL)
        EX     DE,HL
        ADD    HL,DE
        EX     DE,HL
        LD     (HL),D
        DEC    HL
        LD     (HL),E
        DEC    HL
        DEC    HL
        POP    AF
        POP    DE
        EX     (SP),HL
        RET

;---------------------------------------------------------------------------
; Put your code here and add 'R' in front of commands with absolute pointers

Relative_code_start:

        R LD   DE,TXT1
        R CALL PRINT
        LD     A,(#82)
        CP     #60
        JR     C,.SKIP
        SUB    #20

.SKIP:  CP     "@"
        R LD   DE,TXT2
        R CALL Z,PRINT
        R LD   DE,TXT3
        R JP   C,PRINT
        CP     "H"+1
        R JP   NC,PRINT
        R LD   DE,TXT4
        R JP   PRINT


TXT1:   DB     "This is stupid example program:",10,13,0
TXT2:   DB     "This is used in email addresses, it is not ",0
TXT3:   DB     "unknown...",0
TXT4:   DB     "drive letter",0


PRINT:  PUSH   AF
.LOOP:  LD     A,(DE)
        INC    DE
        AND    A
        JR     Z,.EXIT
        RST    #30
        DB     #80
        DW     #A2
        JR     .LOOP
.EXIT:  POP    AF
        RET

Relative_code_end:

Login or register to post comments

By NYYRIKKI

Enlighted (5421)

NYYRIKKI's picture

17-01-2011, 01:58

Ah... there was a reason for that error... It can be fixed by... no... This time I'm not gonna go there... Just remove the 'R' when not needed to make stuff run.

I also forgot to mention that this does not work with commands like LD XX,(YYYYY) or LD (XXXX),YY these commands need to be patched manually... Example:

	CALL Next_is_relative3
	LD (TXT2-$-2),HL

By NYYRIKKI

Enlighted (5421)

NYYRIKKI's picture

17-01-2011, 02:29

**IT! I'm not in the brightest mode today... oO

I just realized that although this works first time, it also destroys it self in the process... the process should be also reversed -> takes even more time... At the moment I would wish there would be a big delete button somewhere...Eek!

ah, well... just forget what I wrote, this is not gonna be a good method after all... Crying

By MicroTech

Champion (384)

MicroTech's picture

17-01-2011, 11:16

Cool stuff Cool
It is always interesting and stimulating for me reading your posts!

If you were an M80/L80 user you could try to replicate a small/custom L80 (to be permanently included in your code) to relocate on-the-fly modules needed which should be resident on disk in .REL format and "org"ed at 0... sounds like DLL Tongue

By sjoerd

Hero (593)

sjoerd's picture

06-02-2011, 20:59

I just realized that although this works first time, it also destroys it self in the process... the process should be also reversed -> takes even more time...

Isn't it possible to zero the call, so the next time the Z80 sees some nops and the instruction that was patched the first time?