6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Sep 21, 2024 3:14 am

All times are UTC




Post new topic Reply to topic  [ 21 posts ]  Go to page Previous  1, 2
Author Message
PostPosted: Sun Jan 20, 2019 6:54 am 
Offline
User avatar

Joined: Tue Nov 16, 2010 8:00 am
Posts: 2353
Location: Gouda, The Netherlands
Downside of mixing code and data is that branches get out of range quicker. For big chunks of data, you could place them somewhere else, and then just use a pointer word after the JSR to get to it.


Top
 Profile  
Reply with quote  
PostPosted: Mon Jan 21, 2019 3:02 pm 
Offline
User avatar

Joined: Mon May 12, 2014 6:18 pm
Posts: 365
Could you use a macro to declare all the strings inline for readability but put their actual declaration somewhere else like a compiler does? Something like this:
Code:
Print   .macro msg
        ???
        .endm
       
        Print "Hello!"
        Print "Test"

After expansion:
Code:
        LDA #<str1
        LDX #>str1
        JSR print_sub
        LDA #<str2
        LDX #>str2
        JSR print_sub
        ...
str1:   .DB "Hello!"
str2:   .DB "Test"


Top
 Profile  
Reply with quote  
PostPosted: Mon Jan 21, 2019 4:03 pm 
Offline
User avatar

Joined: Wed Feb 14, 2018 2:33 pm
Posts: 1467
Location: Scotland
Druzyek wrote:
Could you use a macro to declare all the strings inline for readability but put their actual declaration somewhere else like a compiler does? Something like this:
Code:
Print   .macro msg
        ???
        .endm
       
        Print "Hello!"
        Print "Test"

After expansion:
Code:
        LDA #<str1
        LDX #>str1
        JSR print_sub
        LDA #<str2
        LDX #>str2
        JSR print_sub
        ...
str1:   .DB "Hello!"
str2:   .DB "Test"


Not 100% sure about doing it via a macro, however if using ca65 then you can use separate data and code segments, however it will require writing a suitable config file for it and arranging the loader (or eprom burner) to work out where to put the sections.. So:

Code:
.code
  ldx #>msg1
  ldy #<msg1
  jsr strout

.data
msg1: .byte "Hello, world",13,10,0
.code ; Back to the code segment
  ... more 6502 program code here


This is almost exactly what happens behind the scenes when using cc65 (and other C compilers on operating systems such as Unix/Linux, etc.) It then becomes the linkers problem to work out how to create a file that the loader can recognise and put the sections into the right place in RAM or ROM.

I've had a look at the macro features of ca65 and I'm not sure it can do that though - however if you were clever with something like m4 (that runs under Unix/Linux, etc.) then it's possible - you effectively divert the generated output (ie. the string data) into a temporary file as part of your PRINT macro, then you need an ending macro that pulls the diverted text into the main document at the end. It should be possible to write a macro that uses the segments though - let me check... I don't think so.

It looks like you can change segments - that's fine, but can't change segments inside a macro - at least not with ca65

This is my test file:

Code:
   strout   = $F000 ; Faking it
.org $1000

;
;   .macro   print string
;   .code
;   ldx   #>:+
;   ldy   #<:+
;   jsr   strout
;   .data
;:
;   .asciiz   string
;   .code
;   .endmacro
;
;
;   print   "Hello, world"
;   print   "Another test"
;
;
   .code
   ldx   #>:+
   ldy   #<:+
   jsr   strout
   .data
:
   .asciiz   "Hello World"

   .code
   ldx   #>:+
   ldy   #<:+
   jsr   strout
   .data
:
   .asciiz   "Another Test"


And the assemble & link commands if you want to test it:

Code:
ca65 -g --cpu 65c02 -l test2.lst test2.s
ld65 -t none -S 0x1000 -vm -m test2.map -o test2 test2.o


the one using the macros gets the output file in the right order, but has the wrong addresses for the ldx & ldy instructions. This may well be a bug in ca65 though.

So have a look at the .lst and .map files and comment out the bottom and un-comment the top to experiment.

.... but before I hit submit, I did a few more tests and it looks like you CAN use the macros, however only if you keep it all relocatable until the link state, so no .ORG in the source file, but keep that -S 0x1000 (or whatever) in the link command.

So using the macros, assembling, linking to $1000 (the data segment follows on), the hex output file looks like:

Code:
000000 a2 10 a0 0e 20 00 f0 a2 10 a0 1b 20 00 f0 48 65  >.... ...... ..He<
000010 6c 6c 6f 2c 20 77 6f 72 6c 64 00 41 6e 6f 74 68  >llo, world.Anoth<
000020 65 72 20 74 65 73 74 00                          >er test.<


Which has the offset for the first string at $100e which looks correct... the map file is somewhat confusing, but the relevant lines are:

Code:
Name                   Start     End    Size  Align
CODE                  001000  00100D  00000E  00001
DATA                  00100E  001027  00001A  00001


Now all you need do is create the right config file for cc65 and a loader that can read the .map file and you're there :-)

Cheers,

-Gordon

_________________
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/


Top
 Profile  
Reply with quote  
PostPosted: Mon Jan 21, 2019 5:59 pm 
Offline

Joined: Sat Dec 13, 2003 3:37 pm
Posts: 1004
Arlet wrote:
Downside of mixing code and data is that branches get out of range quicker. For big chunks of data, you could place them somewhere else, and then just use a pointer word after the JSR to get to it.

Well, depending on the data, the inline method may be a touch more compact as there never needs to be actual code referencing the data, much less loading it in to registers.

Consider:
Code:
    JSR add
    db $1234
    db $4567

in contrast to:
Code:
    LDA #<data
    LDX #>data
    JSR add
    ...
data:
    db $1234
    db $4567

In the first effort, the routine implicitly "knows" where the data is, whereas in the second you need 4 bytes to load up registers and whatnot.
Now, obviously the routine is going to chew up some memory to pull the parameters apart, etc.

But given enough calls, there could be a notable decrease in code size at the cost of some performance (as always...).


Top
 Profile  
Reply with quote  
PostPosted: Tue Jan 22, 2019 5:59 am 
Offline

Joined: Tue Jul 24, 2012 2:27 am
Posts: 674
ca65 macros can absolutely generate segment-hopping output, using .pushseg, .segment "foo", .popseg. I use that heavily in AcheronVM and some older projects to generate data tables and even documentation.

_________________
WFDis Interactive 6502 Disassembler
AcheronVM: A Reconfigurable 16-bit Virtual CPU for the 6502 Microprocessor


Top
 Profile  
Reply with quote  
PostPosted: Tue Jan 22, 2019 6:48 am 
Offline
User avatar

Joined: Wed Feb 14, 2018 2:33 pm
Posts: 1467
Location: Scotland
White Flame wrote:
ca65 macros can absolutely generate segment-hopping output, using .pushseg, .segment "foo", .popseg. I use that heavily in AcheronVM and some older projects to generate data tables and even documentation.


One of those cases where you don't know what you don't know... and despite using ca65 for some time now, completely missed pushseg!

However the one thing I found when playing with the stuff above is that it didn't seem to work when you'd specified a .org in the source file and I'm not sure if this is a bug/feature of ca65 or by design.

But now this is opening up some ideas for me...

Cheers,

-Gordon

_________________
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 21 posts ]  Go to page Previous  1, 2

All times are UTC


Who is online

Users browsing this forum: No registered users and 28 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: