Ein Beispiel

 

Am folgenden Beispiel (ist auch in den Demo Programmen enthalten) wird die Struktur von Assemblerroutinen erklärt. Dabei muss in dem Projekt der CompactC Source Code die Endung ".cc" die Assembler Sourcen die Endung ".asm".

 

// CompactC Source

void proc1 $asm("tag1")(void);

int proc2 $asm("tag2")(int a, float b, byte c);

 

int glob1;

void main(void)

{

    int a;

 

    proc1();

    a= proc2(11, 2.71, 33);

}

 

Vor Aufruf der Assembler Prozeduren proc1 und proc2 müssen die beiden Prozeduren erstmal deklariert werden. Dies geschieht mit dem Befehlswort $asm. Die Deklaration sieht in Basic ähnlich aus:

 

' Basic Deklaration der Assembler Routinen

$Asm("tag1") proc1()

$Asm("tag2") proc2(a As Integer, b As Single, c As ByteAs Integer

 

 

Man sieht in der Deklaration die Strings "tag1" und "tag2".  Diese Strings werden in einer ".def" Datei definiert, wenn tatsächlich ein Aufruf der deklarierten Funktionen stattfand. In diesem Fall sieht dann die ".def" Datei folgendermaßen aus:

 

; .def file

.equ glob1 = 2

.define tag1 1

.define tag2 1

 

Setzt man nun im Assembler Source die einzelnen Routinen in ".ifdef ..." Anweisungen, so werden die Routinen nur assembliert, wenn ein Funktionsaufruf wirklich stattfand. Dies spart Platz bei der Codegenerierung. Auch werden in der ".def" Datei die Positionen der globalen Variablen definiert. Die ".def" Datei wird automatisch zusammen mit den Assemblerdateien gemeinsam übersetzt, sie braucht nicht extra inkludiert zu werden.

 

 

Hier folgt nun der Assembler Source der Prozedur proc1. In diesem Source wird die globale Variable glob1 auf den Wert 42 gesetzt.

 

; Assembler Source

.ifdef tag1

proc1:

    ; global variable access example

    ; write 42 to global variable glob1

 

    MOVW R26,R8          ; get RamTop from register 8,9

    SUBI R26,LOW(glob1)  ; subtract index from glob1 to get address

    SBCI R27,HIGH(glob1)

 

    LDI  R30,LOW(42)

    ST   X+,R30

    CLR  R30             ; the high byte is zero

    ST   X,R30

 

  ret

.endif

 

 

Im zweiten Teil des Assembler Sources werden die übergebenen Parameter "a" und "c" als integer addiert, und die Summe dann zurückgegeben.

 

.ifdef tag2
proc2:
    ; example for accessing and returning parameter
    ; we have int proc2(int a, float b, byte c);
    ; return a + c
 
    MOVW R30, R10   ; move parameter stack pointer into Z
    LDD R24, Z+5  ; load parameter "a" into R24,25
    LDD R25, Z+6
 
    LDD R26, Z+0  ; load byte parameter "c" into X (R26)
    CLR R27       ; hi byte zero because parameter is byte
 
    ADD R24, R26  ; add X to R24,25
    ADC R25, R27
 
    MOVW R30, R6      ; copy stack pointer from R6
    ADIW R30, 4       ; add 4 to sp  - ADIW only works for R24 and greater
    MOVW R6, R30      ; copy back to stack pointer location
 
    ST   Z+, R24      ; store R24,25 on stack
    ST   Z, R25
 
    ret
.endif