Jump to content
IGNORED

REPEAT and QSET after ASM instructions


Recommended Posts

 

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 ?

 

Link to comment
Share on other sites

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 by DZ-Jay
  • Like 1
Link to comment
Share on other sites

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 by DZ-Jay
Link to comment
Share on other sites

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"

 

  • Like 1
Link to comment
Share on other sites

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

Link to comment
Share on other sites

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 by DZ-Jay
Link to comment
Share on other sites

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 by DZ-Jay
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

@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 by artrag
bug fixed
Link to comment
Share on other sites

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 by artrag
Link to comment
Share on other sites

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.

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...