fenrock Posted July 13, 2023 Share Posted July 13, 2023 (edited) 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 July 13, 2023 by fenrock changed title after update Quote Link to comment Share on other sites More sharing options...
tebe Posted July 13, 2023 Share Posted July 13, 2023 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) Quote Link to comment Share on other sites More sharing options...
fenrock Posted July 13, 2023 Author Share Posted July 13, 2023 (edited) 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 July 13, 2023 by fenrock Quote Link to comment Share on other sites More sharing options...
fenrock Posted July 13, 2023 Author Share Posted July 13, 2023 (edited) 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 July 13, 2023 by fenrock fix quotes Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted July 13, 2023 Share Posted July 13, 2023 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 ... 1 Quote Link to comment Share on other sites More sharing options...
fenrock Posted July 13, 2023 Author Share Posted July 13, 2023 @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 Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted July 13, 2023 Share Posted July 13, 2023 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 Quote Link to comment Share on other sites More sharing options...
fenrock Posted July 13, 2023 Author Share Posted July 13, 2023 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. Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted July 13, 2023 Share Posted July 13, 2023 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 > Quote Link to comment Share on other sites More sharing options...
fenrock Posted July 14, 2023 Author Share Posted July 14, 2023 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. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.