Using constants OR registers as argument in macros

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'd like to use EITHER a constant or a register as arg0 (@0) in a macro, so that either of the following two cases works:

"MyMacroName $00"

"MyMacroName tempreg" (where tempreg = r16)

In the macro, the only real difference would be that I would be either loading the constant, or moving the register, respectively, to another register.

Thinking that in the case of a constant, the constant would appear 'undefined' to the assembler, in the macro definition I've tried this:

#ifndef @0
ldi r17,@0
#endif

#ifdef @0
mov r17,@0
#endif

but the assembler didn't like like the 'ifndef' when a number was used as arg0 - seemed ok when arg0 was 'tempreg' though.

Any ideas would be appreciated.

-mark

Mark
Elgin, IL (near Chicago)

Last Edited: Wed. Dec 22, 2010 - 01:06 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hand trace your program with pencil and paper.

The C pre-processor only makes a single pass.
So what you have finally written on paper is what the Assembler sees.

Now hand trace these instructions. This is what will finally be assembled.
Now the Assembler can use expressions before hey are finally resolved.

Think in terms of you hand tracing the assembly process multiple times.

Now I am not sure of the semantics of the Assembler's text substitution. i.e. the .xxxxx variety of directive.
It may be single pass or it may allow some forward references.

The Assembler .macro instruction will expand the arguments like @0 etc fresh every time.
However the C preprocessor has already processed the #xxxxx directives.

Simple answer is. Give an example of what you want to achieve. With a combination of #xxxxx, .xxxxx, .macro directives you can do most things!

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The macro assemblers that can keep track of what types different kinds of symbols represent (so that they can decide whether to use "ldi" or "mov" opcodes) are called C compilers. Have you considered using one?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
$ deleted! Double posting annoys people. Please continue in the other thread. $

I would guess that this is the Moderator's message. If the post was an exact copy, it is handy to be informed in this thread. OTOH, was it a reply to this thread?

Yes. It is better to keep to a single thread. It is polite to delete the double post completely.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

try the following:
1)bias all your 8 bit constants you are using in your program by a value larger then RAMEND value in the .inc file of your device ,ie , you should add 0x10000 to all the canstants you use
2)redefine your registers with there numbers ,ie ,for exemple r0's register number will be 0
and when you call your macro use the newly defined values.
for exemple:
#define nR0 0
#define nR1 1
#define nR2 2
#define nR3 3
...
#define nR31 31
// yout constants
#define K1 0x10010 // intended cst value is 0x10
#define K2 0x100AA // intended cst value is 0xAA
#define K3 0x100FF // intended cst value is 0xFF
//if you are calling the macro to process Io locations
//redefine your IOs in terms of memory mapped adresses
// ie IO starts @ 0x20 until 0x5F
// define your macro as follows
.macro Mymacro
.if @0<0x1F
mov r17,r@0
.elif @0<0x5F
in r17;@0 - 0x20
.elif @0<0xFFFF
lds r17,@0
.elif @0<0x20000
ldi r17,@0-0x10000
.elif @0==0x20000 // X0
ld r17,x
.elif @0==0x20001 // Xp
ld r17,x+
.elif @0==0x20001 //nX
ld r17,-x
.endmacro

using this method you can even manage indirect adressing mode by defining
#define X0 0x20000
#define Xp 0x20001
#define nX 0x20002
... do the same for z and y

if you define variables that use register locations,be sure to define them in terms of register numbers, use the following
#define YourVariable nRx // x = 0,...31
and nR0...nR31 suposed to be defined before as mentioned above

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#ifndef @0
ldi r17,@0
#endif 

This certainly would not work since the second parameter to LDI is not a register.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#ifndef @0 

This cannot work because the C preprocessor only runs once. The @0 comes from the assembler.

I do not know. But you can try using the .ifdef version that is interpreted by the assembler.

You can pass anything that you like in the @0.
Just remember that subsequent opcodes have support the register or memory.

Adas_06 shows you how to put conditional code inside a macro.

So it looks as if the #xxxx macros are executed once.
But the .xxxx macros are executed every time that the macro is expanded.

David.