Jump to content
IGNORED

MADS struct questions - How to get size, and fill string data


Recommended Posts

I've raised an issue here, but thought I might get quicker feedback here.

 

Why does the following throw an error?

 

foo.asm

foo .struct
  x .word
  .ends

  org $1000
start
  lda #foo
  sta $80
  rts

  run start

 

Compiling:

$ mads -o:foo.xex -l -t foo.asm
  lda #foo
foo.asm (7) ERROR: Could not use FOO in this context
Writing listing file...

 

The docs say the length of the struct can be got with `lda #structName` but for me it's throwing compile error

 

However...

The listing file shows the correct output:

 

mads 2.1.7
Source: foo.asm
     1                          foo .struct
     2 = 0000                     x .word
     3                            .ends
     4
     5                            org $1000
     6                          start
     7 FFFF> 1000-1004> A9 02     lda #foo
     8 1002 85 80                 sta $80
     9 1004 60                    rts
    10
    11 02E0-02E1> 00 10           run start

 

If I add more fields to the struct, the value at $1001 changes correctly.

 

Edited by fenrock
changed title after update
Link to comment
Share on other sites

v1.9.6
- .LEN (.SIZEOF) directive extended to support data allocated via DTA STRUCT_NAME, e.g.:

.STRUCT free_ptr_struct
  prev .WORD
  next .word
.ENDS

free_ptr_t dta free_ptr_struct [3].

	.print .sizeof(free_ptr_t) ; free_ptr_struct [0..3] = 16 bytes

 

use .LEN or .SIZEOF

 

lda #.sizeof(foo)

 

Link to comment
Share on other sites

Thanks @tebe, that's perfect.

 

.LEN is documented nicely, I hadn't spotted it mentions structs. Just the docs on struct itself, possibly I don't use latest docs

 

Is there a better version in english than https://mads.atari8.info/mads_eng.html ?

I might be reading an older version, or there's a more up to date version, or it may not be updated.

 

Just found 

I'll see if I can contribute. 

Edited by fenrock
Link to comment
Share on other sites

A follow up question, is there a way to initialise a string into a struct?

 

NetConfig .struct
    ssid        :33 .byte  ; 32 + NULL
    password    :64 .byte
.ends



nc dta NetConfig ; ... ? is it possible initialise with something like: (d'12345', d'password')

 

 

Edited by fenrock
fix quotes
Link to comment
Share on other sites

1 hour ago, fenrock said:

A follow up question, is there a way to initialise a string into a struct?

Yes:-

    org $4000
.STRUCT tmp
     ssid  :33  .byte
     pass :64 .byte
.ENDS

mydata DTA tmp[1]\
 ('Qswxy123Bnu67A','Hello World')\
 ('AbCdEf987654321','Hello Goodbye')

 

In memory when loaded:-

 

4000 51 73 77 78 79 31 32 33 Qswxy123
4008 42 6E 75 36 37 41 00 00 Bnu67A..
4010 00 00 00 00 00 00 00 00 ........
4018 00 00 00 00 00 00 00 00 ........
4020 00 00 00 00 00 00 00 00 ........
4028 00 00 00 00 00 00 48 65 ......He
4030 6C 6C 6F 20 57 6F 72 6C llo Worl
4038 64 00 00 00 00 00 00 00 d.......
4040 00 00 00 00 00 00 00 00 ........
4048 00 00 00 00 00 00 00 00 ........
4050 00 00 00 00 00 00 00 00 ........
4058 00 00 00 00 00 00 00 00 ........
4060 00 00 00 00 00 00 00 00 ........
4068 00 00 00 00 00 00 00 00 ........
4070 00 00 00 00 00 00 00 00 ........
4078 41 62 43 64 45 66 39 38 AbCdEf98
4080 37 36 35 34 33 32 31 00 7654321.
4088 00 00 00 00 00 00 00 00 ........
4090 00 00 00 00 00 00 00 00 ........
4098 00 00 00 00 00 00 00 00 ........
40A0 00 00 00 00 00 00 00 47 .......G
40A8 6F 6F 64 62 79 65 20 57 oodbye W
40B0 6F 72 6C 64 00 00 00 00 orld....
40B8 00 00 00 00 00 00 00 00 ........
40C0 00 00 00 00 00 00 00 00 ........
40C8 00 00 00 00 00 00 00 00 ........
40D0 00 00 00 00 00 00 00 00 ........
40D8 00 00 00 00 00 00 00 00 ........
40E0 00 00 00 00 00 00 00 00 ........
40E8 00 00 00 00 00 00 00 00 ........
40F0 00 00 00                ...

  • Like 1
Link to comment
Share on other sites

@TGB1718 I don't think the assembler is getting this correct.

 

It's adding the length of the first string (minus 1), then putting in the second string, and not accounting for the first string's length correctly and subtracting it.

 

In your example, "Hello World" should start at $4021 ($4000 + 33 decimal).

But it starts 13 bytes later at $402e (which is 1 less than the string length of "Qswxy123Bnu67A")

 

The next string "AbCdEf987654321" is starting at $4078, which is 120 bytes after the first, instead of 97, the length of the struct.

 

I wrote a simplified example to demonstrate the error more easily:

        org $1000
.struct tmp
        f1 :8 .byte
        f2 :8 .byte
.ends

d1      dta tmp[1] ('11', '11') ('22', '22')

 

Here each field "f1" and "f2" occupies 8 bytes, which is easy to visualise in a 16 byte hex dump per line.


The output should be:

0000000 31 31 00 00 00 00 00 00 31 31 00 00 00 00 00 00
0000020 32 32 00 00 00 00 00 00 32 32 00 00 00 00 00 00


 

Compiling and dumping out the data gives:

$ mads -t -l -o:foo.xex foo.asm
$ od -t x1 <(tail -c +7 foo.xex)
0000000 31 31 00 00 00 00 00 00 00 31 31 00 00 00 00 00
0000020 00 00 32 32 00 00 00 00 00 00 00 32 32 00 00 00
0000040 00 00 00 00
0000044

 

We can see the first string "11" is at first byte, second "11" should be at byte 8, but it start's at byte 9

Then the first "22" is starting at $22 instead of $20, having been pushed out by 2 bytes (one from each of the two previous strings).

 

Then the second "22" is also pushed out this time by 3 bytes (1 from each of "11", "11", "22").

Finally, there's 4 extra zeroes at the end from $40 to $43, as all 4 strings pushed the final length out by 1 each.

 

Changing this to use longer strings demonstrates the assembler is always adding "length of string - 1" extra bytes into the output.

 

FYI @tebe

Link to comment
Share on other sites

22 minutes ago, fenrock said:

I don't think the assembler is getting this correct.

I think it's the "repeat" that's at fault, done a few tests and something like this seem ok:-

.STRUCT tmp
     ssid    .byte
     pass  .byte
.ENDS

mydata DTA tmp[4] ('11','12') ('11','12') ('11','12') ('11','12')

 

I actually use a load of arrays in a program I'm playing with, it's essentially a matrix of screen

positions that get modified, this is one of 6 similar matrices that use a macro to access them

and it seems to work just fine. Obviously I'm not using the repeat.

 

.STRUCT COLS
    addr1 .word
    mask1 .byte
    addr2 .word
    mask2 .byte
.ENDS

; addresses of the "LIGHTS" in the lower left screen
COL0 DTA COLS[14] \ 
($30F4,$3,$3124,$3) \ 
($3184,$3,$31B4,$3) \ 
($3214,$3,$3244,$3) \
($32A4,$3,$32D4,$3) \
($3334,$3,$3364,$3) \ 
($33C4,$3,$33F4,$3) \
($3454,$3,$3484,$3) \
($34E4,$3,$3514,$3) \
($3574,$3,$35A4,$3) \
($3604,$3,$3634,$3) \
($3694,$3,$36C4,$3) \ 
($3724,$3,$3754,$3) \ 
($37B4,$3,$37E4,$3) \ 
($3844,$3,$3874,$3) \ 
($38D4,$3,$3904,$3)

 

c00 lookup col0[0].addr1,col0[0].addr2,col0[0].mask1,col0[0].mask2

Link to comment
Share on other sites

21 minutes ago, TGB1718 said:

I think it's the "repeat" that's at fault, done a few tests and something like this seem ok:-

.STRUCT tmp
     ssid    .byte
     pass  .byte
.ENDS

mydata DTA tmp[4] ('11','12') ('11','12') ('11','12') ('11','12')

Not sure this is fine, you're trying to put 2 chars into a byte each time, the output is:
 

0000000 31 31 31 31 32 32 32 32

which is mind bending to work out 🤣, it's effectively the string "11112222"

 

I do get your point that it may be the repeat that's at fault as you're clearly using other structs fine.

I couldn't see another way of reserving the space though, the docs use this pattern (e.g. "q :3 .byte   ; lda #name.q = 11" is an example of a struct field in the docs), so we may have to wait for the MADS maintainers to comment on the behaviour.

 

Link to comment
Share on other sites

33 minutes ago, fenrock said:

Not sure this is fine, you're trying to put 2 chars into a byte each time, the output is:

Completely bad mistake on my part, meant to remove the quotes, however that does show it's allocating space for the structure

even though it doesn't make any sense.

 

BUT:- if you put some code to access the structure, you get the wrong data as the code is expecting single bytes:-

 

see this 

 

    org $4000
.STRUCT tmp
     ssid    .byte
     pass  .byte
.ENDS

mydata DTA tmp[4] ('15','32') ('36','78') ('11','12') ('11','12')
    lda mydata[0].ssid
    lda mydata[0].pass
    lda mydata[1].ssid
    lda mydata[1].pass

 

4000 31 35 33 32 33 36 37 38 15323678
4008 31 31 31 32 31 31 31 32 11121112
4010 31 31 31 32 AD 00 40 AD 1112-.@-
4018 01 40 AD 02 40 AD 03 40  @- @- @
4020 00 00 00 00 00 00 00 00 ........
4028 00 00 00 00 00 00 00 00 ........
4030 00 00 00 00 00 00 00 00 ........
4038 00 00 00 00 00 00 00 00 ........
4040 00                      .
>Y4014 4020
4014   LDA  4000      AD 00 40
4017   LDA  4001      AD 01 40
401A   LDA  4002      AD 02 40
401D   LDA  4003      AD 03 40
4020   BRK            00
>

 

Link to comment
Share on other sites

I think you're breaking it the wrong way.
I think it's the user's error trying to put 2 chars into a single byte. The compiler could error I suppose if you're trying that.

 

The bigger issue is when the data DOES fit in the field, but the assembler is adding bytes incorrectly.

 

If you take your own example, and change each field to have ":2" repeat, and re-run, you'll see the data output as:


0000000 31 35 00 33 32 00 33 36 00 37 38 00 31 31 00 31
0000020 32 00 31 31 00 31 32 00 31 31 00 31 32 00 ad 00
0000040 40 ad 02 40 ad 04 40 ad 06 40

 

So each pair of characters is generating 3 bytes instead of 2. All those extra zeros are wrong.

The addressing is fine, it's loading from 4000, 4002, 4004, 4006. These are the correct addresses, but the data is misaligned.

The data is at 4000, 4003, 4006, 4009.

 

So my code is breaking because the data is in the wrong place, even though the code is trying to access the correct memory.

 

A full example showing it's "adding extra by 1 less than string it puts in" is here. For the 1 char case, it correctly assigns 3 bytes, for 2 chars, it assigns 4 bytes, and 3 chars it assigns 5 bytes.

It should only allocate 3 bytes every time.

 

    org $4000
.STRUCT tmp
     ssid  :3 .byte
     pass  :3 .byte
.ENDS

mydata DTA tmp[3] ('1','2') ('34','56') ('789','abc')
    lda mydata[0].ssid
    lda mydata[0].pass
    lda mydata[1].ssid
    lda mydata[1].pass

0000000 31 00 00 32 00 00 33 34 00 00 35 36 00 00 37 38
0000020 39 00 00 61 62 63 00 00 37 38 39 00 00 61 62 63
0000040 00 00 ad 00 40 ad 03 40 ad 06 40 ad 09 40

 

We can see that for "1" it puts in "31 00 00", this is perfect.

We can see that for "2" it puts in "32 00 00", this is perfect.

 

We can see that for "34" it puts in "33 34 00 00" - an extra 00 at the end

We can see that for "56" it puts in "35 36 00 00" - an extra 00 at the end

 

We can see that for "789" it puts in "37 38 39 00 00" - extra 00 00

We can see that for "abc" it puts in "61 62 63 00 00" - extra 00 00

 

All these extra zeroes it puts in are wrong. And it always puts in the number equal to the previous string's length - 1.

So it only gets a single char case correct.

 

I'm less concerned about single byte fields in the struct, that's not an issue (unless you try to put in too much data in your code).

The bug that's affecting me is the valid scenario of trying to initialise with values that fit inside the fields, but the assembler adds extra zeroes in error.

 

@tebe I think this is a bug in the initialising structs from strings code.

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...