Assembly within C

Use the #asm and #endasm directives to delimit blocks of assembly. An assembly block can be located both inside and outside of functions. One important note about this syntax is that all # directives must be the first non white space characters on a line. Therefore #asm and #endasm directives can't be placed in the middle of statements.

C variables are directly accessible from within the assembly block. The C compiler replaces the name of the variable with its address. Whether the variable address is used as an immediate value, or as a direct or indirect address depends on the assembly instruction.

Figure 6-1. Embedded blocks of assembly asm1.c

char arr[10]; /* declare an array of 10 characters */

void main(void)
{
    int i;
    i=sizeof(arr); /* assign the size of arr[] to i */

    /* while(i--) arr[i]=0; */

#asm
    LD B,#arr     ;load B to point to arr
    LD X,#i       ;load X to point to i
clear_arr
    LD S,#i>>8    ;select i RAM bank
    LD A,[X]      ;load i
    DECA          ;decrement
    X  A,[X]      ;store A to i
    IFEQ A,#0     ;done if i is zero
    JP done_clear
    LD S,#arr>>8  ;select arr RAM bank
    CLRA 
    X  A,[B+]     ;clear arr[]
    JP clear_arr  ;clear next byte
done_clear
#endasm
}

    

If you need to return a value from a function written in assembly, you need to follow the same protocol that COP8C code does. If one byte is returned, it is passed though the A register. If two bytes are returned, they are passed using A and X. The most significant byte is placed in X and the least significant byte is placed in A.

Figure 6-2. Setting the function return value from assembly asm1.c

long inc_long(long l) /* increment a long variable */
{
       /* return(++l); */
#asm
        LD  S,#l>>8 ; load high address of l into S
        LD  B,#l    ; load low address of l into B
        RC          ; clear carry
        LD  A,[B]   ; load low byte of l
        ADC A,#1    ; add 1
        X   A,[B+]  ; store result
        LD  A,[B-]  ; load high byte of l
        ADC A,#0    ; add carry to high byte
        X   A,X     ; return high byte in X
        LD  A,[B]   ; return low byte in A
#endasm
}

    

Including assembly into C is convenient when you have some assembly language code you wish to use unchanged.