Memory access when compiling assembler program as a ROM

Page 1/2
| 2

By santiontanon

Paragon (1757)

santiontanon's picture

06-05-2016, 05:01

Hi guys, I have a (perhaps very obvious) question,

I've recently been playing around with programming in assembler for MSX1, and I'm struggling to understand the way memory works when you load your program as a ROM. For example, if in my assembler program, I define some memory values like this:

spriteattributes:
db 64,64,0,15

If I try to modify those later with:
ld (spriteattributes),128

The values do not get modified. If I compile my program as a BIN file, and load it with BLOAD"...",R then the values in spriteattributes can be changed fine, but when I compile as a ROM, then this cannot be done. I am assuming that this is because the program is living in ROM, which is non-modifiable. Is this correct? If it is, then if I want to have variables in RAM, then I guess I cannot define then as in the example above, right?

Login or register to post comments

By Guillian

Prophet (3516)

Guillian's picture

06-05-2016, 12:34

You are right. The problem is that when working with ROMs you must copy the data to RAM if you want to modify it.

I.e.:

    ld hl,spriteattributes
    ld de,sprAttribRAM
    ld bc,4
    ldir
...
    ld a,128
    ld (sprAttribRAM),a
...
spriteattributes:
    db 64,64,0,15
...
    org    #c000
sprAttribRAM: ds 4

or
    map #c000
sprAttribRAM: # 4

By santiontanon

Paragon (1757)

santiontanon's picture

06-05-2016, 16:22

Thanks!!! That makes sense (and worked).

One follow-up question:
- In my little test program, the last lines of code looked like this:

spriteattributes:
    db 64,64,0,15
ship:
    db 00h, 00h, 01h, 01h, 01h, 03h, 03h, 07h, 07h, 0fh, 1fh, 3fh, 3ch, 18h, 00h, 00h
    db 00h, 00h, 80h, 80h, 80h,0c0h,0c0h,0e0h,0e0h,0f0h,0f8h,0fch, 3ch, 18h, 00h, 00h
End:
    ds 8000h - $ - 4

Now if I add the space for RAM variables, then the end looks like this (if I still want the ROM to be a multiple of 16KB, so the emulator can load it):

spriteattributes:
    db 64,64,0,15
ship:
    db 00h, 00h, 01h, 01h, 01h, 03h, 03h, 07h, 07h, 0fh, 1fh, 3fh, 3ch, 18h, 00h, 00h
    db 00h, 00h, 80h, 80h, 80h,0c0h,0c0h,0e0h,0e0h,0f0h,0f8h,0fch, 3ch, 18h, 00h, 00h
End:
    ds 8000h - $ - 4

    org 0c000h
spriteattributesRAM:
    ds 4

But that looks very messy (that "ds 8000h - $ - 4" line looks ugly Wink). Is there a "neater" way to add those variables in the program than the way I did it?

Thanks a lot again for your time!

By Metalion

Paragon (1622)

Metalion's picture

06-05-2016, 17:09

IMHO, there's no other way to do this.
You have no choice but to say to the assembler that your variables are located in $C000, hence the "org".

By flyguille

Prophet (3031)

flyguille's picture

06-05-2016, 17:15

you don't use DS for declaring variables, because that sentence will inflate your BIN file, as (DS = DEFINE SPACE).

what you do is:

org 0c000h
varname: RB 4 (RB = reserve bytes, in this case 4 bytes for that label).
varname2: RW 1 (RW = reserve word, in this case 1 word (16bits) for that label).

and this method don't inflate the file, because it is just reservations, not definitions.

By Grauw

Ascended (10699)

Grauw's picture

06-05-2016, 19:04

RB is tniasm syntax; # is Sjasm syntax; in Glass you use DS VIRTUAL 4. These define space and increase the address counter, while not actually outputting data to the file.

Alternatively, using standard assembler syntax I would do this:

spriteattributesRAM: equ 0C000H
somethingElseInRAM: equ 0C004H  ; or spriteattributesRAM + 4

Etc.

Alternatively, use SECTION in Glass:

restoreaddress:
    org 0C000H
RAM: DS VIRTUAL 1000H   ; some amount of space you do not want to exceed
    org restoreaddress

; ...

    SECTION RAM
spriteattributesRAM: ds 4
somethingElseInRAM: db 1
    ENDS

And, if you make the RAM DS not VIRTUAL, you can easily copy the bytes in the RAM section from their ROM address to RAM as initial values, which I think is the most convenient way:

    ld hl,restoreaddress
    ld de,RAM
    ld bc,1000H
    ldir

But if you do this, you don’t actually really need VIRTUAL or SECTION or # or RB, you can just use standard assembler syntax:

restoreaddress:
    org 0C000H
RAM:

spriteattributesRAM: ds 4
somethingElseInRAM: db 1

RAM_size: equ $ - RAM
    org restoreaddress + RAM_size

And then LDIR it to the RAM address at startup.

By santiontanon

Paragon (1757)

santiontanon's picture

06-05-2016, 17:51

Oh! I see!

I am trying to compile with the Glass compiler, which does not support "rb 4", but looking into the documentation I see that "ds virtual 4" might be the equivalent (just tried it and seemed to work! so, I think I'm set).

Thanks a lot again for the very fast responses guys! Smile

By santiontanon

Paragon (1757)

santiontanon's picture

06-05-2016, 17:52

oh, I responded without noticing Grauw had responded already Smile

Very useful information! thanks!

By NYYRIKKI

Enlighted (6016)

NYYRIKKI's picture

06-05-2016, 20:30

This is the method I use most:

	LD HL,MOVERAM_START
	LD DE,RAM
	LD BC,MOVEROM_END-MOVERAM_START
	LDIR
	.
	.
	.

MOVERAM_START:
	PHASE #C000
;----------------------
RAM:

TABLE1:	DB 1,2,3,4
PARAMS:	DB 5,6,7,8

SETSP:	LD (.STORE),HL
	LD SP,0
.STORE:	EQU $-2
	JP NEXT

;-----------------------

	DEPHASE
MOVERAM_END
	.
	.
	.
	DS ((($-1)/#4000)+1)*#4000-$

By Grauw

Ascended (10699)

Grauw's picture

06-05-2016, 22:40

That’s the same as my last example Smile (though I used org rather than phase). I agree it’s the best one, pre-initialised RAM is just more convenient to work with, also safest: no accidental use of uninitialised value.

santiontanon: The DS at the end aligns to any multiple of 4000H. DS -$ & 3FFFH may also work…

By santiontanon

Paragon (1757)

santiontanon's picture

07-05-2016, 18:17

Oh! that last "ds" line to align adaptively to multiples of 4000h is a neat trick!

Page 1/2
| 2