• PicŪ Basic

  • How much code space our routines have?

    This article is based on an idea and code by Darrel Taylor. How much code space do our routines use? We can find out with some MPASM directives.
    I have created several similar macros. These macros DO NOT use any code space in the PIC. They simply create "Symbols" in the .asm and .list files that indicates the size of the measured code.
    To measure the size of any code block, simply place a declaration at the beginning of the code:
    Next, place after the code block:

    To simplify and order these operations it is better to use an extension for each type of routine, for example for the macros:

    For the subroutines:
    ENDSIZE (Name_LIB)

    For the code in the main program:

    Example of a macro made with the preprocessor.
    $define HEXtoASCII2(pValueIn,pReturn1,pReturn2) '
        STARTSIZE(HEXtoASCII2_MACRO)                '
        EEDATA = pValueIn                           '
        _mHEXtoASCII2                               '
        pReturn1 = PRODH                            '
        pReturn2 = PRODL                            '
    In the .asm file it can be read.
        movff MyInputByte,EEDATA
    variable max_params=10,_mHEXtoASCII2_return=0,prm_count=0
        rcall HEXtoASCII2_Sub
        movff PRODH,MyASCIIH
        movff PRODL,MyASCII
    MESSG SIZE_CODE#HEXTOASCII2_MACRO = 14[BYTES]                              = 7[WORDS]
    You can see that the macro always starts with:

    And it always ends with:

    At least you can know where your code is and what size it has. By extension I have created another calculation allowing measurement of the time of execution of the code. This value would be real if there were neither subroutines called by a Gosub nor iterations in loops. Anyway, this calculation could be an idea of time.

    To obtain all this information regarding the code, you must enable the macros by this definition before the file.
    $define __MEASURE_CODE_

    If the calculations are disabled then the codes will be marked by their name in this way.
        movff MyInputByte,EEDATA
    variable max_params=10,_mHEXtoASCII2_return=0,prm_count=0
        rcall HEXtoASCII2_Sub
        movff PRODH,MyASCIIH
        movff PRODL,MyASCII
    Include file:
    In an .inc (library) file if all the routines were tagged, it would be easy to know how all the compiled code is used, for example:

    At the top of the file and before the code insert this macro.

    At the end of the file and after the code insert this macro. You can write the name of the file.

    The result compiled bytes in asm.file is:

    Library "TIPS_and_TRICKS_V10.INC":
    I gathered in a single file a few macros that could be useful for PDS users. You will see that I have compiled some old macros too.
    There are all the definitions and statements that you might need. In addition I have attached a new version of the library of local variables. You can study all the tricks used to make macros.

    20/09/2018 Update library Tips_and_Tricks_V11.inc.

    I have fixed some little errors.

    Continuing with the BCD counters, I have written some codes allowing very large calculations with some unpacked integer BCD arrays. The only advantage I see in the BCD counters is that it can be easily visualized in the terminal, on the LCD display or been received/sent by a serial communication.
    On the web there is some information about calculations with the packed BCD bytes. The assembler has an instruction (Daw) for the BCD calculations. But it's not good for the arrays. Then I had to write the codes from the beginning. The most difficult codes to write have been the multiplication and especially the division.

    BCD Arrays:
    For the whole system to work correctly, I have created 8 arrays. 4 Arrays are for the use of the PDS user and 4 more for the internal calculations.


    ADD_BCD(Nb Array1,Nb Array2,Nb Array3)
    The calculation is done in this way: Array3 = Array1 + Array2
    To simplify the task, to identify an array, only the number is written, not the name.

    ADD_BCD(1,2,3) or ADD_BCD(1,2,4)
    In the ADD_BCD macro, an overflow control is provided that can be consulted.
    ErrorVar = ADD_BCD(1,2,3) If ErrorVar = 1 an overflow has occurred.
    In the end the code is very simple, considering that you can add a very large number of digits.


    SUB_BCD(Nb Array1,Nb Array2,Nb Array3)
    With overflow control: ErrorVar = SUB_BCD(1,2,3)

    The code is a bit more complex because the minuend is destroyed by the calculations. I have considered keeping it so that the user can continue making calculations with the same numbers.


    Logically, multiplication is a sum of additions. If done in this way, the calculation time would be too long. To see this principle I have written the macro MULV_BCD.
    Then a displacement of the divisor is made to the left, which corresponds to multiplying it by 10. And the number of sums of each corresponding number of the multiplicand is made. Which considerably reduces the number of repetitions.
    456 X 123 = 56088

    456 x 3 = 1368
    4560 x 2 = 9120
    45600 x 1 = 45600
    Total = 56088

    Multiplier X Multiplicand = Product
    MUL_BCD(Nb Array1,Nb Array2,Nb Array3)
    With overflow control: ErrorVar = MUL_BCD(Nb Array1,Nb Array2,Nb Array3)
    The multiplier is restored at the end because it has been destroyed.


    Logical, division is a sum of subtractions. Is done in this way, the calculation time would be too too long. (more than 60 seconds)
    The technique used is that of children who learn division in elementary school. It is easy to do with a pen and paper but difficult to pass to code when the number of digits is very important.

    458 / 12 = 38, remainder 2

    4 5 8 | 1 2
    - 3 6 _____
    = 0 9
    9 8 3 8
    - 9 6
    = 0 2

    The multiplier is restored at the end because it has been destroyed also.

    Transfers of values between variables and the BCD counters:

    STR_BCDArray(Nb Array, Variable In)
    Import a word to the BCD array number 1.
    STR_BCDArray(1, InputWord)

    Variable In could be a Byte/Word or Dword.

    Variable = VAL_BCDArray(Nb Array)
    The value of the array is extracted to a Byte/Word or Dword.
    Of course the values of the array must be the same size as the external variable.

    HRSOut_BCDarray(Nb Array,Nb of CarriageReturn)
    This command allows to send any BCD array to the terminal.
    HRSOut_BCDarray(4,2) The Array4 is sent to the terminal with 2 Carriages Return.

    Print_BCDarray(Nb Array,Line,Position)
    This command allows to send any BCD array to the display LCD.
    Print_BCDarray(2,1,5) Send the array number 2 to the LCD in line 1 and raw 5.

    I have tried some calculations of more than 64 bits without any problem.
    The execution time, which is important, depends on the number of BCD counters chosen. It is always preferable to have a little more than necessary to avoid overflow.

    In addition you can find more than 26 macros in the library that will help you in your projects.

    21/09/2018:Version 1.2 Fixed an errata with __KEYPAD_PORT.

    For any supplementary information use the forum in the wiki section.
    Download the code from HERE.

    Alberto Freixanet September 2018.
  • Recent Activity


    Pulse counter memory problem

    Thread Starter: amod

    Please tell me my faults.My pulse counter memory does not store.When i switch on device after 5 second ,memory exist by after 30 seconds it is washed...

    joesaliba Today, 18:33 Go to last post