Replace all occurances of <> with !=
Replace all = in if statements with == (you will get "Missing right parethesis" as the error if you forget this)
Replace all OR in if statements with ||
Replace all AND in if statements with &&
Replace all NOT in if statemetns with !
Local directives must be on the VERY NEXT line after the macro statement.
Parameters are passed to Macros in SASM by name and in SXKey by value. If you have a macro that compiles some code and then a jump to an address which is passed as a parameter, and you call the macro with <macroname> $ when $ is, for example, 0010, in the SXKey, the macro will compile a jump to 0010. In SASM the macro will compile a jump to the value of $ at the time the jump is compiled (it will always make an endless loop). You can override this by calling the macro with <macroname> ?$ but if the macro compiles the jump with jmp @\1 it will cause an "Symbole <#> is not defined" error; instead, you must compile the jump with jmp C<@$??\1> (see the SASM manual section 4.4.2 "Token Pasting"). You can also compensate by defining a local var in the macro, setting the var to \1 before any code is compiled and then useing the var rather than the parm when the jump is compiled.
Debugging macros is somewhat hindered by the fact that the line number of the error is reported at the line where the macro is called followed by the line where the actual error occurs in the list file, but if there are errors, you can't get a list file with Ctrl-L... however, the list file is generated and can be opened seperatly to show the actual error in the macro.
In the SX Key assembler, dot values (like the bit number of a port pin) are actually multiplied by $100 and added to the main number. E.g. RA.1 is $105. So... if you defined a constant like RS232Tx = RA.1 and then later wanted a mask to xor against the port to toggle the bit (I know, read-modify-write, this is just an example) you could do something like xor ra, #(1<<(RS232Tx / $100)) and it would make the correct mask. Just in case it isn't clear, the advantage of this is that if, later down the road, you changed RS232Tx = RA.2, the mask would automatically correct itself. SASM Keeps these values as fractions (apparently) so RA.1 is $5.1. After stratching around for a while, I found that the DOT operator (.) also works to convert a dot value back into a bit number. So if you have RS232Tx = RA.1 the value of .RS232Tx is 1. And, believe it or not, ..RS232Tx is .1. Confused yet? Ok, anyway, the mask can be made with xor ra,#(1<<(.RS232Tx))
mymacro MACRO
mytest2 = 1
ENDM
org 0000
;--------------- SX INTERRUPT VECTOR --------------------
; INTERRUPT
RETI ; RETURN FROM INTERRUPT
;---------------------------------------------------------
;---------------- Place YOUR CODE here ------------------
SX_RESET
mov !RC,#01111111b
MAIN
; mytest1 = 1
; mymacro
:LOOP XOR RC,#80h
; mytest3 = 1
mymacro
JMP :LOOP
1 ;******* Little program: blinking LED connected to port RC.7 *****
2
3 0FFB 0F7F DEVICE PINS28,OPTIONX
4
5 mymacro MACRO
6 mytest2 = 1
7 ENDM
8 =00000000 org 0000
9
10 ;--------------- SX INTERRUPT VECTOR --------------------
11 =00000000 INTERRUPT
12 0000 000E RETI ; RETURN FROM INTERRUPT
13 ;---------------------------------------------------------
14
15 ;---------------- Place YOUR CODE here ------------------
16 0001 0C7F SX_RESET mov !RC,#01111111b ; 0002 0007
17 =00000003 MAIN
18 ; mytest1 = 1
19 ; mymacro
20 0003 0C80 :LOOP XOR RC,#80h
0004 01A7
21 ; mytest3 = 1
22 mymacro
23 =00000001 m mytest2 = 1
25 0005 0A00 JMP :LOOP
****** testsasm.asm(23) Line 25, Error 3, Pass 2: Symbol <mytest2:LOOP> is not defined
26 ;----------------------------------------------------------
27
28 ;=== Don't use SASM's 'RESET' directive, always place this code at the end of your source ---
29
30 =000007FF ORG 07FFh ;Reset Vector for 2K code configuration
31 07FF 0A01 JMP SX_RESET
32 end
Cross Reference
6 symbols
Symbol Type Value Line
INTERRUPT ADDR 00000000 0011
MAIN ADDR 00000003 0017
MAIN:LOOP ADDR 00000003 0020
mytest2 VAR 00000001 0023
RC RESV 00000007 0020
SX_RESET ADDR 00000001 0016
In the SX Key, this compiles just fine. It understands that the mytest2 = 1 is NOT defining a lable for the MAIN area.
;******* Little program: blinking LED connected to port RC.7 *****
DEVICE SX28L,STACKX_OPTIONX
mymacro MACRO
mytest2 = 1
ENDM
000- org0000
;--------------- SX INTERRUPT VECTOR --------------------
000- ; INTERRUPT
000- 00E RETI ; RETURN FROM INTERRUPT
;---------------------------------------------------------
;---------------- Place YOUR CODE here ------------------
001- C7F 007 SX_RESET mov !RC,#01111111b
003- MAIN
; mytest1 = 1
; mymacro
003- C80 1A7 :LOOP XOR RC,#80h
; mytest3 = 1
005- mymacro
=00000001 mytest2 = 1
005- A03 JMP :LOOP
;----------------------------------------------------------
end
Comments:
Some other differences between the two assemblers:The Parallax assembler will split strings in macro arguments to several arguments with a single character in each. The SASM assembler does not.
SOME_MACRO 'ABC'will be converted to
SOME_MACRO 'A','B','C'by the Parallax assembler but not by the SASM assembler.
The '%' sign can not be used in the same way inside a rept block when it is used in an expression that will evaluate to an argument number in a macro:
SOME_OTER_MACRO macro rept 1 dw \%,\(%+1) endr endmThe dw \%,\(%+1) will be expanded to:
dw \1,\2 with the Parallax assembler but to
dw \1,\,2 with the SASM assembler, where the single '\' will be expanded to the number of arguments given to the macro (same as \0).Ruben
See: