|
Navigation: Compiler > Assembler > Ein Beispiel |
![]() ![]()
|
Am folgenden Beispiel (ist auch in den Demo Programmen enthalten) wird die Struktur von Assemblerroutinen erklärt. Dabei muß 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 Byte) As 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 R28, R10 ; move parameter stack pointer into Y
LDD R26, Y+5 ; load parameter "a" into X (R26)
LDD R27, Y+6
LDD R30, Y+0 ; load byte parsmeter "c" into Z (R30)
CLR R31 ; hi byte zero because parameter is byte
ADD R26, R30 ; add Z to X
ADC R27, R31
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+, R26 ; store X on stack
ST Z, R27
ret
.endif