artrag Posted July 4, 2022 Share Posted July 4, 2022 In Intybasic I'm trying to make this code work ASM indx QSET 0 ASM REPEAT 8 ASM MVII #label_&SOFTBULLETS,R4 ASM ADD array_BULFRAME+indx,R4 ASM REPEAT 4 ASM MVI@ R4, R1 ASM MVO@ R1, R5 ASM SWAP R1 ASM MVO@ R1, R5 ASM ENDR ASM indx QSET indx+1 ASM ENDR But it seems that I cannot define a variable lavel with QSET with the ASM command What am I doing wrong here ? Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted July 5, 2022 Share Posted July 5, 2022 (edited) 4 hours ago, artrag said: In Intybasic I'm trying to make this code work ASM indx QSET 0 ASM REPEAT 8 ASM MVII #label_&SOFTBULLETS,R4 ASM ADD array_BULFRAME+indx,R4 ASM REPEAT 4 ASM MVI@ R4, R1 ASM MVO@ R1, R5 ASM SWAP R1 ASM MVO@ R1, R5 ASM ENDR ASM indx QSET indx+1 ASM ENDR But it seems that I cannot define a variable lavel with QSET with the ASM command What am I doing wrong here ? I've encountered this before. The assembler expects labels on the first column, otherwise it will interpret the string as an opcode. It seems that IntyBASIC does not inject the ASM code at the start of the left margin, and so the assembler won't accept the label. Unfortunately, it is therefore impossible to declare assembler symbols from IntyBASIC using the ASM directive. The solution is to write the code in a separate module as a normal assembly file, and have the assembler include it (instead of IntyBASIC) inline with an "ASM INCLUDE." dZ. Edited July 5, 2022 by DZ-Jay 1 Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted July 5, 2022 Share Posted July 5, 2022 (edited) To be sure, it does not seem to be a bug. My guess is that, because IntyBASIC does not really parse the assembly code following the ASM directive, it has no way of knowing if what follows is a label declaration or an opcode. It therefore assumes that everything is actual code. The alternative would be to require all statements with assembly code to leave more than one space between the ASM directive and the rest, which seems a bit brittle and unintuitive. In reality, the ASM directive was intended for single statements. More complex code should be factored out into its own module anyway. dZ. Edited July 5, 2022 by DZ-Jay Quote Link to comment Share on other sites More sharing options...
artrag Posted July 5, 2022 Author Share Posted July 5, 2022 The command ASM INCLUDE grambullts.asm gives error at the assembly time How to include external asm file ? Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted July 5, 2022 Share Posted July 5, 2022 3 hours ago, artrag said: The command ASM INCLUDE grambullts.asm gives error at the assembly time How to include external asm file ? Needs quotation marks: ASM INCLUDE "grambullts.asm" 1 Quote Link to comment Share on other sites More sharing options...
artrag Posted July 5, 2022 Author Share Posted July 5, 2022 Yes thanks 1 Quote Link to comment Share on other sites More sharing options...
artrag Posted July 8, 2022 Author Share Posted July 8, 2022 Is it possible to use labels in REPEAT/ENDR blocks without incurring in " ERROR - multiple definition of label" ? Other assemblers allow relative labels or labels that incoroprate the number of iteration but I cannot find anything symilar in as1600 Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted July 8, 2022 Share Posted July 8, 2022 (edited) 22 minutes ago, artrag said: Is it possible to use labels in REPEAT/ENDR blocks without incurring in " ERROR - multiple definition of label" ? Other assemblers allow relative labels or labels that incoroprate the number of iteration but I cannot find anything symilar in as1600 Ah, yes. That was addressed in the assembler with a new construct to generate non-recurring labels. I don’t recall right now how it goes (something like “%%”), but you should be able to find it in the assembler’s documentation. (Or wait until I get home and I’ll look it up.) Alternatively, you could do it the old-school way, the way we did it before that feature, exploiting array symbols: _i QSET 0 REPEAT 5 MyLabel[_i]: ; code, code, code _i QSET (_i + 1) ENDR dZ. UPDATE: Note that the underscore has no significance in the label. I just tend to prefix private labels with an underscore. Edited July 8, 2022 by DZ-Jay Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted July 8, 2022 Share Posted July 8, 2022 (edited) 4 hours ago, DZ-Jay said: Ah, yes. That was addressed in the assembler with a new construct to generate non-recurring labels. I don’t recall right now how it goes (something like “%%”), but you should be able to find it in the assembler’s documentation. (Or wait until I get home and I’ll look it up.) Alternatively, you could do it the old-school way, the way we did it before that feature, exploiting array symbols: _i QSET 0 REPEAT 5 MyLabel[_i]: ; code, code, code _i QSET (_i + 1) ENDR dZ. UPDATE: Note that the underscore has no significance in the label. I just tend to prefix private labels with an underscore. I looked it up, but it turns out I misremembered. There is indeed a special symbol "%%," but it applies to the macro pre-processor only. It expands to the number of macro expansions performed so far, which is useful for generating unique labels within macros. You will have to employ something like my previous example, because a macro (and therefore the special symbol) won't work for your purpose. You see, even if you define a macro to generate unique labels, it won't work within a REPEAT block. That is because the macro pre-processor runs before the assembler (as you know), so a macro within the REPEAT block will be expanded exactly once -- it is then the assembler who repeats the block multiple times. It would result in the same label being repeated. The assembler and the macro expander are combined in the same executable, but in reality, they are two separate components. I believe there are some "hooks" between them, but I believe Joe has said that, generally, those are mostly hacks to implement some special feature. I do use macros for this sort of thing, but they merely encapsulate the construct I offered in my example. I set up a global counter somewhere in some library, and have a macro increment it and return a unique value. Still, old-school, "hacky" stuff. ; Somewhere at the top of your code ... _lbl_cnt QSET 0 MACRO UniqueLabel(prefix) ; %prefix%[_lbl_cnt]: LISTING "code" _lbl_cnt QSET (_lbl_cnt + 1) LISTING "prev" ENDM You would use it like this: ; Sample Use: REPEAT UniqueLabel(foo) ; code, code, code ENDR It results in code like this: REPEAT 5 ;UniqueLabel(foo) ; 0x0 foo[_lbl_cnt]: ; code, code, code ;== 1 ENDR ;UniqueLabel(foo) ; 0x0 foo[_lbl_cnt]: ; code, code, code ;== 2 ENDR ;UniqueLabel(foo) ; 0x0 foo[_lbl_cnt]: ; code, code, code ;== 3 ENDR ;UniqueLabel(foo) ; 0x0 foo[_lbl_cnt]: ; code, code, code ;== 4 ENDR ;UniqueLabel(foo) ; 0x0 foo[_lbl_cnt]: ; code, code, code ;== 5 ENDR Cheers! -dZ. Edited July 8, 2022 by DZ-Jay Quote Link to comment Share on other sites More sharing options...
artrag Posted July 9, 2022 Author Share Posted July 9, 2022 Thanks. I will try this solution Strange that as1600 doesn't include these features Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted July 9, 2022 Share Posted July 9, 2022 15 minutes ago, artrag said: Thanks. I will try this solution Strange that as1600 doesn't include these features Maybe so, but as someone who's been using it for over 10 years, I've seen it improve greatly in that time. Array symbols, slices, string manipulation, symbol classification -- all these have just been introduced within the past few years. As I understand it, it didn't even have a macro pre-processor -- that was created as a separate project, built as a separate executable, and eventually integrated by Joe Z. later on. The as1600 assembler (and the jzIntv integrated debugger) truly has been an evolving project influenced by many people, but engineered and maintained by a single person, Joe Zbiciak, in his spare time. Sure, it can always be improved and enhanced, but -- for whatever my personal opinion is worth -- I find it exceedingly powerful. In my own development framework, I leverage the pre-processor heavily as a code-generator for a high-level(ish) pseudo language that supports a sort of structured, object-oriented, component-based assembly model. Anyway, the solution of using an array symbol with a global counter is sound, and it is what most of us have used in the past, so you're in good company. -dZ. Quote Link to comment Share on other sites More sharing options...
artrag Posted July 13, 2022 Author Share Posted July 13, 2022 (edited) @DZ-Jay I'm trying to make your label idea work within a REAPEAT/ENDR loop. Get plenty of errors becouse the counter does not get replaced and becouse the macro label cannot be used in Branch instructions... Are you sure about the code you posted ? Do you have any idea about what can be wrong in this code: _lbl_cnt QSET 0 MACRO UniqueLabel(prefix) %prefix%[_lbl_cnt] _lbl_cnt QSET _lbl_cnt + 1 ENDM indx QSET 0 REPEAT 7 MVI array_ES+indx,R0 TSTR R0 BEQ UniqueLabel(_Next) MVI var_TX,R0 MVI var_TY,R1 MVI array_&EX+indx,R2 SWAP R2 ANDI #255,R2 MVI array_&EY+indx,R3 SWAP R3 ANDI #255,R3 CALL TESTBOX TSTR R0 BEQ UniqueLabel(_Next) ;dummy sound MVII #330,R0 MVO R0,498 SWAP R0 MVO R0,502 MVII #48,R0 MVO R0,509 ;dummy sound MVII #500,R0 MVO R0,499 SWAP R0 MVO R0,503 MVII #9,R0 MVO R0,506 CLRR R0 MVO R0,array_ES+indx MVII #array_BULS,R1 ADD var_I,R1 MVO@ R0,R1 MVII #76,R0 MVO R0,var_BLX MVII #44,R0 MVO R0,var_BLY B _End UniqueLabel(_Next): indx QSET indx + 1 ENDR _End: Edited July 13, 2022 by artrag bug fixed Quote Link to comment Share on other sites More sharing options...
artrag Posted July 13, 2022 Author Share Posted July 13, 2022 (edited) I did it work, thanks. Without macro is is fine indx QSET 0 REPEAT 7 MVI array_ES+indx,R0 TSTR R0 BEQ _Next[indx] ;[275] if (USR TESTBOX(tx,ty,#ex(j)/256,#ey(j)/256)) then MVI var_TX,R0 MVI var_TY,R1 MVI array_&EX+indx,R2 SWAP R2 ANDI #255,R2 MVI array_&EY+indx,R3 SWAP R3 ANDI #255,R3 CALL TESTBOX TSTR R0 BEQ _Next[indx] ;[278] sound 2,330,48 MVII #330,R0 MVO R0,498 SWAP R0 MVO R0,502 MVII #48,R0 MVO R0,509 ;[279] sound 3,500,9 MVII #500,R0 MVO R0,499 SWAP R0 MVO R0,503 MVII #9,R0 MVO R0,506 CLRR R0 MVO R0,array_ES+indx MVII #array_BULS,R1 ADD var_I,R1 MVO@ R0,R1 MVII #76,R0 MVO R0,var_BLX MVII #44,R0 MVO R0,var_BLY B _End _Next[indx]: indx QSET indx + 1 ENDR _End: Edited July 13, 2022 by artrag Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted July 13, 2022 Share Posted July 13, 2022 1 hour ago, artrag said: @DZ-Jay I'm trying to make your label idea work within a REAPEAT/ENDR loop. Get plenty of errors becouse the counter does not get replaced and becouse the macro label cannot be used in Branch instructions... Are you sure about the code you posted ? Do you have any idea about what can be wrong in this code: _lbl_cnt QSET 0 MACRO UniqueLabel(prefix) %prefix%[_lbl_cnt] _lbl_cnt QSET _lbl_cnt + 1 ENDM indx QSET 0 REPEAT 7 MVI array_ES+indx,R0 TSTR R0 BEQ UniqueLabel(_Next) MVI var_TX,R0 MVI var_TY,R1 MVI array_&EX+indx,R2 SWAP R2 ANDI #255,R2 MVI array_&EY+indx,R3 SWAP R3 ANDI #255,R3 CALL TESTBOX TSTR R0 BEQ UniqueLabel(_Next) ;dummy sound MVII #330,R0 MVO R0,498 SWAP R0 MVO R0,502 MVII #48,R0 MVO R0,509 ;dummy sound MVII #500,R0 MVO R0,499 SWAP R0 MVO R0,503 MVII #9,R0 MVO R0,506 CLRR R0 MVO R0,array_ES+indx MVII #array_BULS,R1 ADD var_I,R1 MVO@ R0,R1 MVII #76,R0 MVO R0,var_BLX MVII #44,R0 MVO R0,var_BLY B _End UniqueLabel(_Next): indx QSET indx + 1 ENDR _End: Sorry, I got delayed in getting to this question. Quite simple: in my code, note that there is a “;” on its own line on the very first line of the contents of the macro. This is to force the macro expander to inject a new line so that the label starts at the first column. Otherwise, the label will be injected in place, right after that BEQ. The macro expander removes surrounding white spaces from the contents, so adding an empty line at the top is not sufficient. The “;” is respected as a comment and injected into the output steam, along with its trailing new-line. Its a “trick of the trade.” it’s always a good idea to start your macros with a semi-colon — unless you want it to be injected inline (like a function). Cheers! dZ. 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.