2

I'm programming for the Sega Mega Drive using vasm 1.7d assembler. I'm copying a block of my code from ROM to RAM so I can do some self-modifying code.

        ; First $200 bytes are header, dc.b declarations etc.
RAM_BEGIN = $00FF0000
entry_point:
        ; Copy (cool_routine_in_rom_source, cool_routine_in_rom_source+SIZE-1) to RAM_BEGIN
        lea     cool_routine_in_rom_source,a0
        lea     RAM_BEGIN,a1
        move.w  #(SIZE-1),d0
copy_loop:        
        move.b  (a0)+,(a1)+
        dbf     d0,copy_loop
        jmp     cool_routine_in_ram_entry_point

        align   2
cool_routine_in_rom_source = *
        org     RAM_BEGIN
cool_routine_in_ram_entry_point:
        ; Some code here that uses absolute addressing and self-modifying code.
cool_routine_in_ram_some_label1:
        ; code
        rts
cool_routine_in_ram_some_label2:
        ; code
        rts
        align   2
SIZE = (*-cool_routine_in_ram_entry_point)

If I assemble this using the command:

vasmm68k_mot_win32.exe -Fbin -o main.bin main.68k.asm

I get a binary that contains entry_point then ~16 megabytes of zero padding up to address $00FF0000 then my cool_routine_in_ram code.

Some assemblers (for 6502) let you change the current address while assembling the output consecutively by assigning to * but I don't think vasm accepts that syntax.

What I want is entry_point and cool_routine to be assembled consecutively in ROM, with the second routine (and all labels following it) being assembled as if the PC was at RAM_BEGIN. What is the correct directive/approach to use?

| improve this question | | | | |
  • My current workaround is to compile all of the routines that are entirely RAM-resident in their own source file into a .bin that I can then incbin into the outer layer 'master' file which contains the main entry point. If you start a file with ORG $FF0000 directly, vasm doesn't generate the 16 megabytes of padding to get to that address. That gives me a self-consistent $FF0000-based bin that the outer layer entry point can copy into place and jump to. – Gero Dec 25 '19 at 17:40
  • This only works if the two different sets of code don't need to call one another since they won't be aware of each other's labels, which works well enough for me. – Gero Dec 25 '19 at 17:48
2

Look at phase/dephase directives (also known as rorg/rend) - e.g. in the vasm manual. The whole code should like:

org real_entry_point
entry_point: 
...
align 2
rorg RAM_BEGIN
cool_routine
... (will be assembled for "org RAM_BEGIN", but stored immediately after previous code)
rend
| improve this answer | | | | |
  • Thanks for the hint :) According to the vasm documentation, it seems that rorg and rend (and by extension phase) are only available in the 'oldstyle' syntax module "suitable for some 8-bit CPUs (6502, 680x, 68HC1x, Z80, etc.).". If I alter my dc.l constants into defl and remove 'regs' lists for subroutines, it does assemble correctly with rorg as expected. A way to do this without losing the normal 68000 features would be more convenient though. – Gero Dec 25 '19 at 14:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.