Mixing External Assembly Module with HI-Tech C This is the general format form mixing HI-Tech C with external assembly language modules. You have to understand the Assembly language used by Hi-Tech C is not exactly the same as the PIC's assembly--but follows the same principles. ( All externally available variables, labels, and symbols are first, then the code section designators, and finally, the code in the specified section). The assembly used by this C compiler uses macros and predefined memory segment labels. To limit the commenting at this point, I will only describe the sections important to calling externally defined assembly routines that will to be written in Hi-Tech C's macro assembly language. The only way to call an externally defined (meaning written in another file) assembly language subroutine is to make sure that the function label is globally accessible, ensure that HI-Tech C’s assembly language macro, PSECT, is used to place the assembly coded routine in the correct position in the final compiled assembly file, and when needed, where to find function elements in memory such as passed routine parameters, and return function return values in memory so that it functions correctly with the compiler’s generated code. In order to know the important memory locations, an understanding of how this compiler sets up its values in a given C coded modules is important (you have to know how to interpret addresses seen in a disassembly listing). The assembly language symbols made available by this C compiler are only available to assembly code written in the same C file; however, you have to know what the symbols are in order to understand what the addresses mean. You have to plan your code out first then read the disassembly to figure out where the appropriate addresses are in the assembly code. This is because the location of a function’s parameter variables and return values can vary depending on globally defined variables. To start, parameter values are passed in a section of memory referred to as function parameter space--if the parameter count is greater than 1 and greater than 8 bits. If the parameter count is 1, and it is an 8 bit value, the value is passed to the function through WREG. If the parameter count is greater than 1, and the first parameter is a byte in length, then the 1st parameter is passed into the function through WREG and the other values are placed in the function area. (There is function parameter space for each function being called--when it is called. The function parameter space is programmable accessed using the symbol pattern, ?_<c function name>, where <c function name> is the name of the c function. Mixing External Assembly Module Page 1 Look at the following call to an external function. In this external assembly module, the function's parameter space starts at ?_Dummy16BitAdd. To get access to the two parameters of the function, understand that parameter's a and b are both 2 bytes and the PIC's memory bank’s are 8 bits wide. Because of this, 2 bytes takes up 2 memory slots. The lower byte address is the lower byte of a; the higher address is the upper byte of a. So, the variable a has memory locations ?_Dummy16BitAdd set for its lower byte, and ?_Dummy16BitAdd + 1 for variable a's upper byte. Variable b has ?_Dummy16BitAdd + 2 for its lower byte and b's upper byte is at memory location ?_Dummy16BitAdd + 3. Dummy16BitAdd(15,12); 0040 300F MOVLW 0xf 0041 00A3 MOVWF 0x23 0042 01A4 CLRF 0x24 0043 300C MOVLW 0xc 0044 00A5 MOVWF 0x25 0045 01A6 CLRF 0x26 0046 20D3 CALL 0xd3 In this code snippet from the main function in the main.c file, the call to the external function Dummy16BitAdd(15,12) has a proto-type of extern int Dummy16BitAdd(int a, int b). The extern key word means that this function is defined in another file. In the above disassembly, the start of the memory set up by the compiler for passed function variables starts at location 0x23. This is means that ?_Dummy16BitAdd is located at 23H. This also means that variable a' lower byte is located at 23H, a<15:8> is located at 24H (?_Dummy16BitAdd + 1), b<7:0> is located at 25H (?_Dummy16BitAdd + 2), and b<15:8> falls to memory location 26H (?_Dummy16BitAdd + 3). The return value of a function is placed in a memory location sectioned off by the compiler called btemp (a section no larger than 4 bytes)--if the return value from the function is larger than 1 byte; otherwise, it is returned in WREG. For example, the return value of the function below is greater than 1 byte, the return value is returned in the memory location set off by the C compiler called btemp. The lower byte of the return value is at btemp, and the upper byte is at btemp + 1. In order to determine the memory location of a return value, you have to make up another dummy function and see where the values are being returned to. The following code snippet explains how to interpret the disassembly. Mixing External Assembly Module Page 2 return 500; 00AC 30F4 MOVLW 0xf4 00AD 00FE MOVWF 0x7e 00AE 3001 MOVLW 0x1 00AF 00FF MOVWF 0x7f This return statement from a function has the following disassembly that shows that the compiler has set aside memory locations 7eH (btemp) and 7fH (btemp+1) for a function’s return value usage. This is the main function that calls the external subroutine. #include <htc.h> extern int Dummy16BitAdd(int a, int b); void main(void) { Dummy16BitAdd(15,12); asm(“SLEEP”); } The external routine’s assembly module looks like this. Mixing External Assembly Module Page 3 #include <aspic.h> ; Predefined Register symbols here global _Dummy16BitAdd ParamStart a_Start b_Start ReturnStart ReturnLow ReturnHigh equ 0x23 /* reading disassembly show this is start of parameters to function */ equ 0x23 // 16 bit variable a start here equ 0x25 // 2 byte variable b starts here equ 0x7e // return addresses start here equ 0x7e equ 0x7f PSECT text0,local,class=CODE,delta=2 _Dummy16BitAdd: MOVF b_Start, W ADDWF b_Start movf b_Start, W movwf ReturnLow /*return address for return types greater than 1 byte instead of using WREG */ btfss CARRY movlw 0 movlw 1 movwf ReturnHigh Mixing External Assembly Module Page 4