stack and macro little question!

Discussion in 'Embedded Systems and Microcontrollers' started by Eric007, Dec 25, 2011.

  1. Eric007

    Thread Starter Senior Member

    Aug 5, 2011
    1,044
    33
    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!
     
  2. MrChips

    Moderator

    Oct 2, 2009
    12,442
    3,361
    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.
     
  3. Eric007

    Thread Starter Senior Member

    Aug 5, 2011
    1,044
    33
    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...
     
  4. Eric007

    Thread Starter Senior Member

    Aug 5, 2011
    1,044
    33
    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!
     
  5. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    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.
    Code ( (Unknown Language)):
    1. UDIV1608  macro
    2.  
    3. ;       restore = 9/21 clks,  nonrestore = 8/14 clks
    4.  
    5. ;       Max Timing: 8*9+1+8*21 = 241 clks
    6.  
    7. ;       Min Timing: 8*8+1+8*14 = 177 clks
    8.  
    9. ;       PM: 241                                 DM: 6
    10.  
    11.                 variable i = 0
    12.  
    13.                 while i < 8
    14.  
    15.                 RLF             AARGB0,W
    16.                 RLF              REMB0, F
    17.                 MOVF            BARGB0,W
    18.                 SUBWF           REMB0, F
    19.  
    20.                 BTFSC           _C
    21.                 GOTO            UOK68#v(i)              
    22.                 ADDWF           REMB0, F
    23.                 BCF             _C
    24. UOK68#v(i)      RLF     AARGB0, F
    25.  
    26.                 variable i =i+1
    27.  
    28.                 endw
    29.  
    30.                 CLRF            TEMP
    31.  
    32.                 variable i = 8
    33.  
    34.                 while i < 16
    35.  
    36.                 RLF             AARGB1,W
    37.                 RLF             REMB0, F
    38.                 RLF             TEMP, F
    39.                 MOVF            BARGB0,W
    40.                 SUBWF           REMB0, F
    41.                 CLRF            AARGB5
    42.                 CLRW
    43.                 BTFSS           _C
    44.                 INCFSZ          AARGB5,W
    45.                 SUBWF           TEMP, F
    46.  
    47.                 BTFSC           _C
    48.                 GOTO            UOK68#v(i)              
    49.                 MOVF            BARGB0,W
    50.                 ADDWF           REMB0, F
    51.                 CLRF            AARGB5
    52.                 CLRW
    53.                 BTFSC           _C
    54.                 INCFSZ          AARGB5,W
    55.                 ADDWF           TEMP, F
    56.  
    57.                 BCF             _C
    58. UOK68#v(i)      RLF             AARGB1, F
    59.  
    60.                 variable i =i+1
    61.  
    62.                 endw
    63.  
    64.                 endm
     
    Eric007 likes this.
  6. CraigHB

    Member

    Aug 12, 2011
    127
    15
    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.
     
    Eric007 likes this.
  7. AlexR

    Well-Known Member

    Jan 16, 2008
    735
    54
    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
    Code ( (Unknown Language)):
    1. if(event)
    2. {
    3.     porta |= (1 << 5)    //set bit 5 of porta
    4. }
    5. else
    6. {
    7.     porta &= ~(1 << 5)    //clear bit 5 of porta
    8. }    
    Using macros the code would be as shown below and it is so self explanatory the even the comments are redundent.
    Code ( (Unknown Language)):
    1. #define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
    2. #define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
    3. #define toggle_bit(ADDRESS,BIT) (ADDRESS ^= (1<<BIT))
    4. #define test_bit(ADDRESS,BIT) (ADDRESS & (1<<BIT))
    5.  
    6. ....................................................
    7. ....................................................
    8.  
    9. if(event)
    10. {
    11.     set_bit(porta, 5);    
    12. }
    13. else
    14. {
    15.     clear_bit(porta, 5);  
    16. }    
    17.  
     
    Eric007 likes this.
  8. MrChips

    Moderator

    Oct 2, 2009
    12,442
    3,361
    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.
     
  9. Eric007

    Thread Starter Senior Member

    Aug 5, 2011
    1,044
    33
    Humm...I like the above!
     
  10. Eric007

    Thread Starter Senior Member

    Aug 5, 2011
    1,044
    33
    Thanks all!!
     
  11. MMcLaren

    Well-Known Member

    Feb 14, 2010
    759
    116
    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;

    Code ( (Unknown Language)):
    1.  
    2. ;
    3. ;  in main code -- print a string
    4. ;
    5.         call    putStr          ; print in-line string            |B0
    6.         dt      "hello world\0" ;                                 |B0
    7.  
    Code ( (Unknown Language)):
    1.  
    2. ;
    3. ;  putStr subroutine - pull in-line string address from top of
    4. ;  stack, print string up to the null terminator, then return
    5. ;  to the address immediately following the in-line string.
    6. ;
    7. putStr
    8.         banksel TOSL            ; bank 31                         |B31
    9.         movf    TOSL,W          ; top of stack lo                 |B31
    10.         movwf   FSR1L           ;                                 |B31
    11.         movf    TOSH,W          ; top of stack hi                 |B31
    12.         movwf   FSR1H           ;                                 |B31
    13.         bsf     FSR1H,7         ; set FSR1.15 for rom access      |B31
    14. getchar
    15.         moviw   INDF1++         ; null terminator?                |B?
    16.         bz      putexit         ; yes, exit, else                 |B?
    17.         call    PutDat          ; send char to LCD                |B?
    18.         bra     getchar         ; loop                            |B?
    19. putexit
    20.         banksel TOSL            ; bank 31                         |B31
    21.         movf    FSR1L,W         ; adjust return address           |B31
    22.         movwf   TOSL            ;                                 |B31
    23.         movf    FSR0H,W         ;                                 |B31
    24.         movwf   TOSH            ;                                 |B31
    25.         movlb   0               ; bank 0                          |B0
    26.         return                  ;                                 |B0
    27.  
    Using a macro as a wrapper of sorts can make your code feel a little more intuitive;

    Code ( (Unknown Language)):
    1.  
    2.  
    3. PutStrg macro   string
    4.         call    putStr          ; print in-line string
    5.         dt      string,0        ; null terminated in-line string
    6.         endm
    7.  
    Code ( (Unknown Language)):
    1. ;
    2. ;  example using the PutStrg macro
    3. ;
    4.         PutStrg "Hello World"   ;
    5.  
     
  12. Eric007

    Thread Starter Senior Member

    Aug 5, 2011
    1,044
    33
    Thanks MMclaren...I really appreciate that!
     
Loading...