stack and macro little question!

Thread Starter

Eric007

Joined Aug 5, 2011
1,154
Hi All!

Sorry for my stupid question but yeah I just wana know...

I have never used the stack and macros in my coding...but people seem to be using that (well that what I think)...

So I want to know in what circumstances:

1. using the 'stack' is important and/ or necessary?
2. using 'macros' are important and/ or necessary?

Thanks all for your comment!
 

MrChips

Joined Oct 2, 2009
20,914
You have probably already used the stack without realizing it. Every time you call a subroutine or an interrupt handler you are using the stack.

A subroutine and a macro are similar. They are used when ever you want to repeat a task that you have already coded. In the case of a subroutine, there is only one copy of the code sitting in memory and it is called whenever you need to perform that task.

In a macro, the code is inserted inline where ever you need to execute that task. Naturally, a macro takes up more memory space but executes faster because it does not require a call to the subroutine and a return instruction, and does not have to save and restore registers using the stack.
 

Thread Starter

Eric007

Joined Aug 5, 2011
1,154
Thx very much MrChips! It all clear now...

So how to check the stack usage? I don't know if I'm asking it right but if I remember right I saw somewhere (can't remember exactly) in a template...a stack usage was mentioned...
 

Thread Starter

Eric007

Joined Aug 5, 2011
1,154
In a macro, the code is inserted inline where ever you need to execute that task. Naturally, a macro takes up more memory space but executes faster because it does not require a call to the subroutine and a return instruction, and does not have to save and restore registers using the stack.
This is well explained and I understood but then how do you decide whether you need to use a macro or subroutine?? Coz in most of our codes we use subroutines a lot...but in a few case I see macros...

So when is it important or necessary to use macro? Or it just a preference...

Thx!
 

Markd77

Joined Sep 7, 2009
2,806
Macros can do some useful things, although I tend to avoid them.
This one from Microchip AN526, for example, creates when compiled several copies of the assembler in the while loops and also changes the label and the goto instruction so they are not duplicates.
Rich (BB code):
UDIV1608  macro

;       restore = 9/21 clks,  nonrestore = 8/14 clks

;       Max Timing: 8*9+1+8*21 = 241 clks

;       Min Timing: 8*8+1+8*14 = 177 clks

;       PM: 241                                 DM: 6

                variable i = 0

                while i < 8

                RLF             AARGB0,W
                RLF              REMB0, F
                MOVF            BARGB0,W
                SUBWF           REMB0, F

                BTFSC           _C
                GOTO            UOK68#v(i)              
                ADDWF           REMB0, F
                BCF             _C
UOK68#v(i)      RLF     AARGB0, F

                variable i =i+1

                endw

                CLRF            TEMP

                variable i = 8

                while i < 16

                RLF             AARGB1,W
                RLF             REMB0, F
                RLF             TEMP, F
                MOVF            BARGB0,W
                SUBWF           REMB0, F
                CLRF            AARGB5
                CLRW
                BTFSS           _C
                INCFSZ          AARGB5,W
                SUBWF           TEMP, F

                BTFSC           _C
                GOTO            UOK68#v(i)              
                MOVF            BARGB0,W
                ADDWF           REMB0, F
                CLRF            AARGB5
                CLRW
                BTFSC           _C
                INCFSZ          AARGB5,W
                ADDWF           TEMP, F

                BCF             _C
UOK68#v(i)      RLF             AARGB1, F

                variable i =i+1

                endw

                endm
 

CraigHB

Joined Aug 12, 2011
127
I don't think I've ever used a macro. They're more to reduce repetetive typing than to actually do something on the machine level.

I do stuff with the stack sometimes. For the 8 bit parts, you can manipulate the program counter and stack pointer to return a value from a table coded into program memory. For the 16 bit parts, you use a table read for that, but the stack is more handily available with those. You actually have to configure the stack and allocate memory at initialization of code. Stack values are located in normal data space and are normally addressable. Though, other than initial setup, I have never had a need to change a value.
 

AlexR

Joined Jan 16, 2008
732
Macros certainly reduces repetitive typing but their real value is that they can make your code clearer and easier to read.
For example I often use "bit twiddling" macros to manipulate micro-controller ports and registers. Without the use of macros I could write
Rich (BB code):
if(event)
{
    porta |= (1 << 5)    //set bit 5 of porta
}
else
{
    porta &= ~(1 << 5)    //clear bit 5 of porta
}
Using macros the code would be as shown below and it is so self explanatory the even the comments are redundent.
Rich (BB code):
#define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#define toggle_bit(ADDRESS,BIT) (ADDRESS ^= (1<<BIT))
#define test_bit(ADDRESS,BIT) (ADDRESS & (1<<BIT))

....................................................
....................................................

if(event)
{
    set_bit(porta, 5);    
}
else
{
    clear_bit(porta, 5);   
}
 

MrChips

Joined Oct 2, 2009
20,914
I agree with AlexR. While macros are more efficient than subroutines in execution times, the real purpose of a macro is to create a new instruction that enhances the original instruction set.
 

MMcLaren

Joined Feb 14, 2010
842
May I provide a practical assembly language example which contains a macro and uses the stack? It's a method for storing constant string arrays (string tables) in-line with your code, which seems more intuitive (to me) when compared to storing strings tables all in one spot at the beginning or end of your program. It's also more efficient than other methods once you have more than one or two strings.

Basically, you place the string table with a null terminator (0x00) immediately following a call instruction to a PutStr subroutine. The PutStr subroutine pulls the return address (the string address) from the top-of-stack and reads characters from the string one at a time and sends them to your PutLCD or Put232 routine, up until the null terminator, at which time it replaces the return address on the top-of-stack with the address of the instruction immediately following the string table. Here's what it looks like on enhanced mid-range devices;

Rich (BB code):
;
;  in main code -- print a string
;
        call    putStr          ; print in-line string            |B0
        dt      "hello world\0" ;                                 |B0
Rich (BB code):
;
;  putStr subroutine - pull in-line string address from top of
;  stack, print string up to the null terminator, then return
;  to the address immediately following the in-line string.
;
putStr
        banksel TOSL            ; bank 31                         |B31
        movf    TOSL,W          ; top of stack lo                 |B31
        movwf   FSR1L           ;                                 |B31
        movf    TOSH,W          ; top of stack hi                 |B31
        movwf   FSR1H           ;                                 |B31
        bsf     FSR1H,7         ; set FSR1.15 for rom access      |B31
getchar
        moviw   INDF1++         ; null terminator?                |B?
        bz      putexit         ; yes, exit, else                 |B?
        call    PutDat          ; send char to LCD                |B?
        bra     getchar         ; loop                            |B?
putexit
        banksel TOSL            ; bank 31                         |B31
        movf    FSR1L,W         ; adjust return address           |B31
        movwf   TOSL            ;                                 |B31
        movf    FSR0H,W         ;                                 |B31
        movwf   TOSH            ;                                 |B31
        movlb   0               ; bank 0                          |B0
        return                  ;                                 |B0
Using a macro as a wrapper of sorts can make your code feel a little more intuitive;

Rich (BB code):
PutStrg macro   string
        call    putStr          ; print in-line string
        dt      string,0        ; null terminated in-line string
        endm
Rich (BB code):
;
;  example using the PutStrg macro
;
        PutStrg "Hello World"   ;
 
Top