XA: * manipulations

Questions, bug reports, features requests, ... about the Oric Software Development Kit. Please indicate clearly in the title the related element (OSDK for generic questions, PictConv, FilePack, XA, Euphoric, etc...) to make it easy to locate messages.

christian
Pilot Officer
Posts: 96
Joined: Sun Nov 24, 2013 9:58 pm

XA: * manipulations

Post by christian »

I'm trying to translate some macros from CA65 to XA.

One of them takes a string as parameter and puts the length of this string followed by the string:

Code: Select all

pstring "TEST"
is expanded:

Code: Select all

.byte 4,$54,$45,$53,$54
To do so, I write this XA macro:

Code: Select all

#define pstring(s) -_start=* : .byte 0,s : -_end=* : -_len=_end - _start -1 : *=_end

pstring("TEST")
But the object file is:

Code: Select all

00000000  00 54 45 53 54 04                                 |.TEST.|
With the length after the string...

Then, I'm writing the code below to trace the '*' pointer

Code: Select all

	* = $0400
#print *

_table_start:
	.byte $00,$00,$33,$44,$55

	; We are at $0405 (1029)
_table_end:
#print *

	; Back to start of program
	* = $400
_back:
#print *
	.word $2211
	; Now, we should have
	; 0400 11 22 33 44 55

	; * should be $0402 (1026)
#print *
_table2:

	; Forward to $0405 (1029)
	* = _table_end
#print *

	.byte $66,$77
	; Now, we should have
	; 0400 11 22 33 44 55 66 77

	; * should be $0407 (1031)
_end:
#print *

	; Should be
	; 0407 ad 02 04

	lda _table2
The xa -v -l out.l test2.s output is:

Code: Select all

Cross-Assembler 65xx V2.2.5 (No date available) 
(c) 1989-98 by A.Fachat
65816 opcodes and modes coded by Jolse Maginnis
Oric C adaptation and debugging by Mickael Pointier
Clean Linux port by Jean-Yves Lamoureux
Fri Apr 14 19:05:55 2017
xAss65: Pass 1: test2.s
*=*=1024
*=*=1029
*=*=1024
*=*=1026
*=*=1029
*=*=1031
xAss65: Pass 2:
Statistics:
        5 of     5000 label used
        0 of    40000 byte label-memory used
        0 of    10000 PP-defs used
        0 of  1000000 byte PP-memory used
      225 of   400000 byte buffer memory used
        0 blocks used
        0 seconds used
The '*' pointer's values are correct and the labels values are correct too:

Code: Select all

0400 _table_start
0405 _table_end
0400 _back
0402 _table2
0407 _end
So everything seems ok, but the object file is:

Code: Select all

00000000  00 00 33 44 55 11 22 66  77 ad 02 04              |..3DU."fw...|
Again, the 11 22 is after the 55.

Note the lda _table2 is correctly assembled as ad 02 04

So the value of the '*' is following all affectations, same for all labels, but the bytes are not at the right place.
Since I set '*' only to already used addresses, I thought I can do that.

Is there a way to write this kind of macro?
User avatar
iss
Wing Commander
Posts: 1637
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

Re: XA: * manipulations

Post by iss »

This definition:

Code: Select all

* = $400
#define pstring(s) .byte _end-_start : _start=* : .byte s : _end=*
pstring("TEST")
is assembled as:

Code: Select all

0x00000000: 04 54 45 53 54 -> .TEST
Is this what you are looking for?
User avatar
Dbug
Site Admin
Posts: 4438
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: XA: * manipulations

Post by Dbug »

It's probably possible to use .( and .) in the macro to avoid the label redefinition error if pstring(s) is called multiple time :)

On a side note, while looking at the history of Defence Force today I discovered that Twilighte had used the wiki to document some issues he had in XA.
I guess I should check if they still happen, and if yes add them to the issue tracker: http://wiki.defence-force.org/doku.php? ... :osdk:main
User avatar
iss
Wing Commander
Posts: 1637
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

Re: XA: * manipulations

Post by iss »

As described in XA man page:
To explicitly declare redefinition of a label, place a - (dash) before it
And this code is working for me:

Code: Select all

.text
* = $400
#define pstring(s)  -_start=* : .byte _len,s : -_end=* : -_len=_end - _start - 1
pstring("TEST1")
pstring("TEST2")
The result is:

Code: Select all

0x00000000: 05 54 45 53 54 31 05 54 45 53 54 32 ->  .TEST1.TEST2
@christian: I think there is no way to force XA to go back and to "patch" the zero value in '.byte 0,s' with the calculated length value. If I correctly understand your idea... ;)
christian
Pilot Officer
Posts: 96
Joined: Sun Nov 24, 2013 9:58 pm

Re: XA: * manipulations

Post by christian »

@iss: yes, it's the idea

I've already tried something like your macro but it's not really working:

Code: Select all

#define pstring(s) -_start=* : .byte _len,s : -_end=* : -_len=_end - _start -1

pstring("TEST")
pstring("TEST2")
pstring("TEST33")
The result is

Code: Select all

----------\/-------------\/-----------------\/
00000000  06 54 45 53 54 04 54 45  53 54 32 05 54 45 53 54  |.TEST.TEST2.TEST|
00000010  33 33                                             |33|
Note the first byte, it's 06 but should be 04, the 6th is 04 but should be 05 and the 12th is 05 but should be 06
christian
Pilot Officer
Posts: 96
Joined: Sun Nov 24, 2013 9:58 pm

Re: XA: * manipulations

Post by christian »

@Dbug: Yes it works :D

Code: Select all

#define pstring(s) .( : -_start=* : .byte _len,s : len=* - _start -1 : .)

pstring("TEST")
pstring("TEST2")
pstring("TEST33")
Result

Code: Select all

----------\/-------------\/-----------------\/
00000000  04 54 45 53 54 05 54 45  53 54 32 06 54 45 53 54  |.TEST.TEST2.TEST|
00000010  33 33                                             |33|
Thank you all
christian
Pilot Officer
Posts: 96
Joined: Sun Nov 24, 2013 9:58 pm

Re: XA: * manipulations

Post by christian »

For those interested, here is the final code for this macro (header). Its purpose is to create a header for a Forth's word

Code: Select all

; __lfa need to be defined BEFORE the first use of the macro for 2 reasons:
; 	1) Fisrt LFA must be 0
; 	2) If not defined, all LFA point to the its own NFA
;
__lfa=0
#define header(name,lastc,mode,label) .( : __nfa=* : .byte __len|mode,name,lastc|$80 : __len=* - __nfa -1 : .word __lfa : -__lfa=__nfa : .) : +label = *
;               ^     ^    ^     ^
;               |     |    |     +----> Label (CFA)
;               |     |    +----------> Mode: _NORMAL | _IMMEDIATE
;               |     +---------------> Last character of the NFA
;               +---------------------> NFA (except last character)
;
;
;         .byte mode|lenght(name+lastc)  ;\ NFA
;         .byte name, $80|lastc          ;/
;         .word link to previous NFA     ;  LFA
;
; label:                                 ;  CFA
;

;
; Tools
;
#define code(name,lastc,mode,label) header(name,lastc,mode,label) : .word *+2

; #define word(name,lastc,mode,label) header(name,lastc,mode,label) : .word DOCOLON

#define constant(name,lastc,value,mode,label) header(name,lastc,mode,label) : .word DOCONS : .word value
#define variable(name,lastc,value,mode,label) header(name,lastc,mode,label) : .word DOVAR : .word value
#define user(name,lastc,offset,mode,label) header(name,lastc,mode,label) : .word DOUSER : .byte offset

;
; Modes
;
_NORMAL = $80
_IMMEDIATE = $C0

;
; Tests
;

* = $0400

header("TES","T"  , _NORMAL   ,TEST  )
header("TEST","2" , _IMMEDIATE,TEST2 )
header("TEST3","3", _NORMAL   ,TEST33)

header("","I",_NORMAL,I)

code("COD","E",_NORMAL,CODE)

.word TEST,TEST2,TEST33,CODE

And the result:

Code: Select all

00000000  84 54 45 53 d4 00 00 c5  54 45 53 54 b2 00 04 86  |.TES....TEST....|
00000010  54 45 53 54 33 b3 07 04  81 c9 0f 04 84 43 4f 44  |TEST3........COD|
00000020  c5 18 04 25 04 07 04 0f  04 18 04 23 04           |...%.......#.|
It's more tricky than with CA65 and I think I can't convert all macros from CA65 to XA, but I'll try...
Post Reply