K (→Siehe auch) |
|||
(9 dazwischenliegende Versionen von 3 Benutzern werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
==Bascom Inside== | ==Bascom Inside== | ||
+ | ===Stacks & Frame=== | ||
+ | Bascom arbeitet mit drei Bereichen: | ||
+ | * HW-Stack, | ||
+ | * Software-Stack und | ||
+ | * Frame. | ||
+ | Beschrieben ist das im „HELP“. | ||
+ | Zusätzlich wird noch das | ||
+ | * Register r6 für spezielle Flags verwendet (Bit #2 im Register 6 ist das ERR-Bit) | ||
+ | [[Bild:Stack1.jpg]] | ||
+ | ====Hw-(Hardware-)Stack==== | ||
+ | Der Hardware-Stack ist sozusagen der "normale" Stack, der von den Controllern durch den Stack-Pointer und entsprechende Befehle unterstützt wird. | ||
+ | BasCom verwendet ihn natürlich für CALL / RET / RETI / PUSH und POP. | ||
+ | ====Sw-(Software-)Stack==== | ||
+ | Für Pointer auf temporäre Daten und die Parameter für SUB und FUNCTION hat BasCom einen eigenen Stack definiert. Er liegt unterhalb des Hardwarestacks. | ||
+ | ====Frame==== | ||
+ | Für die temporäre Daten selbst wird der Frame-Bereich verwendet | ||
+ | |||
+ | ===Definition=== | ||
+ | $framesize = 32 ' die Größe des Frames | ||
+ | $swstack = 32 ' die Größe des Software-stacks | ||
+ | $hwstack = 32 ' die Größe des Hardware-Stacks | ||
+ | |||
+ | Die tatsächlich benötigten Größen sind schwer zu errechnen. | ||
+ | Einige Anhaltspunkte: | ||
+ | * Bei jedem Interrupt werden schon mal 32 Byte HW-Stack sicher verbraten, nur, um alle Register zu sichern. | ||
+ | * Jedes "LOCAL" Data verbraucht Frame-Space in seiner Größe + 2 byte auf dem Soft-Stack | ||
+ | * Jeder Parameter einer "SUB" braucht 2 Byte SoftStack + die Datengröße, wenn zusätzlich "byval" angegeben ist. | ||
+ | * datenkonversionen Zahl --> string brauchen die Stringlänge ( PRINT !) | ||
+ | |||
+ | Für ein anständiges Programm sind die Default-Werte auf jeden Fall viel zu klein. | ||
+ | Im Zweifelsfall so groß wie möglich, besonders der SoftStack. | ||
+ | |||
+ | |||
+ | ===Lokale Daten=== | ||
+ | |||
+ | Für lokale Daten muß natürlich erstmal ein Platz geschaffen werden. BasCom verwendet dazu das Frame, die Adresse der Daten legt er auf den Software-Stack. | ||
+ | Alle Datentypen werden gleich behandelt, nur die reservierte Byte-Länge ist relevant. | ||
+ | BasCom schreibt die erforderliche Länge des Items nach R24 und ruft eine interne Function auf.Diese sichert erst den Frame-Pointer (r4:r5) auf dem Software-Stack, erhöht den Frame-Pointer um den verlangten Wert und kehrt zurück | ||
+ | |||
+ | ====reserve space==== | ||
+ | LOCAL Einbyte AS BYTE | ||
+ | |||
+ | .... | ||
+ | LDI r24,$01 // gewünschte Länge = immediate value | ||
+ | CALL AddFrame | ||
+ | .... | ||
+ | |||
+ | AddFrame: | ||
+ | ST --Y,r5 // Store & Save Frampointer Hi | ||
+ | ST --Y,r4 // Store & Save Frampointer LO | ||
+ | ADD r4,r24 // addieren der gewünschten Länge auf den FramePointer | ||
+ | CLR r24 | ||
+ | ADC r5,r24 // ev. carry - Überlauf | ||
+ | RET | ||
+ | |||
+ | Dadurch befindet sich die Adresse des lokalen Datums auf | ||
+ | |||
+ | Y + 0 // Adresse LSB | ||
+ | Y + 1 // Adresse MSB | ||
+ | |||
+ | und steht dort (natürlich nur innerhalb der Function oder Subroutine) zu Verfügung | ||
+ | |||
+ | |||
+ | ====unreserve==== | ||
+ | Vor dem "Return" der Subroutine oder Function muß natürlich alles wiederhergestellt werden | ||
+ | BasCom hat natürlich mitgezählt, wieviel Platz benötigt wurde, und er weiß auch, wieviele solcher Adressen er auf den Soft-Stack gelegt hat. | ||
+ | |||
+ | ….. | ||
+ | ADIW YL,$0002 // Addieren auf den Software Stack Pointer | ||
+ | LDI r24,$01 // Subtrahieren vom Frame Pointer (z.b. 1 Byte ) | ||
+ | CALL SubR4 | ||
+ | RET // return Sub or Function | ||
+ | |||
+ | SubR4: | ||
+ | SUB r4,r24 | ||
+ | CLR r24 | ||
+ | SBC r5,r24 | ||
+ | RET | ||
+ | |||
+ | ===Call Sub & Function=== | ||
+ | |||
+ | Die Parameter an die Funktion / Sub werden über den Softstack übergeben. | ||
+ | Außer für den eigentlichen CALL der Function / Sub wird der HW-Stack hier nicht verwendet. | ||
+ | |||
+ | Es gibt an sich zwei Übergabe-Varianten: BYVAL und BYREF, es wird aber immer BYREF (Addresse von) verwendet, der Unterschied liegt nur darin, dass bei | ||
+ | BYVAL die Addresse einer Daten-Kopie statt des Originals übergeben wird. Die Reihenfolge ist von links nach rechts, wobei die Adresse des Ergebnisses (Funktion) | ||
+ | als erstes auf den Soft-Stack gelegt wird wird. | ||
+ | |||
+ | '''Folgenden Deklarationen führen im Programm zum gleichen Code''' | ||
+ | Declare Function MyFunc (byval Op1 as byte, byval Op2 as byte) as byte | ||
+ | Declare Sub MySub (byref Result as byte , byval Op1 as byte, byval Op2 as byte) | ||
+ | |||
+ | Die Situation beim Aufruf der Funktion / Sub sieht nun folgendermaßen aus, den HW-Stack nicht berücksichtigend | ||
+ | |||
+ | [[Bild:Stack2.jpg]] | ||
+ | |||
+ | Die Funktion / Sub findet nun (beim Entry) | ||
+ | |||
+ | OP2 auf Y + 0/1 | ||
+ | OP1 auf Y + 2/3 | ||
+ | Result auf Y + 4/5 | ||
+ | |||
+ | Verwendet die Funktion / Sub nun selbst den SW-Stack oder das Frame, muß sie das natürlich bei den Y-Offsets berücksichtigen und vor dem Return muß der obige | ||
+ | Zustand auch wiederhergestellt werden. | ||
+ | |||
+ | |||
+ | ==Siehe auch== | ||
+ | * [[Bascom]] | ||
+ | * [[Bascom Inside-Code]] | ||
+ | [[Kategorie:Microcontroller]] | ||
[[Kategorie:Grundlagen]] | [[Kategorie:Grundlagen]] | ||
[[Kategorie:Software]] | [[Kategorie:Software]] | ||
+ | [[Kategorie:Quellcode Bascom]] |
Aktuelle Version vom 24. Februar 2008, 16:21 Uhr
Inhaltsverzeichnis
Bascom Inside
Stacks & Frame
Bascom arbeitet mit drei Bereichen:
- HW-Stack,
- Software-Stack und
- Frame.
Beschrieben ist das im „HELP“. Zusätzlich wird noch das
- Register r6 für spezielle Flags verwendet (Bit #2 im Register 6 ist das ERR-Bit)
Hw-(Hardware-)Stack
Der Hardware-Stack ist sozusagen der "normale" Stack, der von den Controllern durch den Stack-Pointer und entsprechende Befehle unterstützt wird. BasCom verwendet ihn natürlich für CALL / RET / RETI / PUSH und POP.
Sw-(Software-)Stack
Für Pointer auf temporäre Daten und die Parameter für SUB und FUNCTION hat BasCom einen eigenen Stack definiert. Er liegt unterhalb des Hardwarestacks.
Frame
Für die temporäre Daten selbst wird der Frame-Bereich verwendet
Definition
$framesize = 32 ' die Größe des Frames $swstack = 32 ' die Größe des Software-stacks $hwstack = 32 ' die Größe des Hardware-Stacks
Die tatsächlich benötigten Größen sind schwer zu errechnen. Einige Anhaltspunkte:
- Bei jedem Interrupt werden schon mal 32 Byte HW-Stack sicher verbraten, nur, um alle Register zu sichern.
- Jedes "LOCAL" Data verbraucht Frame-Space in seiner Größe + 2 byte auf dem Soft-Stack
- Jeder Parameter einer "SUB" braucht 2 Byte SoftStack + die Datengröße, wenn zusätzlich "byval" angegeben ist.
- datenkonversionen Zahl --> string brauchen die Stringlänge ( PRINT !)
Für ein anständiges Programm sind die Default-Werte auf jeden Fall viel zu klein. Im Zweifelsfall so groß wie möglich, besonders der SoftStack.
Lokale Daten
Für lokale Daten muß natürlich erstmal ein Platz geschaffen werden. BasCom verwendet dazu das Frame, die Adresse der Daten legt er auf den Software-Stack. Alle Datentypen werden gleich behandelt, nur die reservierte Byte-Länge ist relevant. BasCom schreibt die erforderliche Länge des Items nach R24 und ruft eine interne Function auf.Diese sichert erst den Frame-Pointer (r4:r5) auf dem Software-Stack, erhöht den Frame-Pointer um den verlangten Wert und kehrt zurück
reserve space
LOCAL Einbyte AS BYTE
.... LDI r24,$01 // gewünschte Länge = immediate value CALL AddFrame ....
AddFrame: ST --Y,r5 // Store & Save Frampointer Hi ST --Y,r4 // Store & Save Frampointer LO ADD r4,r24 // addieren der gewünschten Länge auf den FramePointer CLR r24 ADC r5,r24 // ev. carry - Überlauf RET
Dadurch befindet sich die Adresse des lokalen Datums auf
Y + 0 // Adresse LSB Y + 1 // Adresse MSB
und steht dort (natürlich nur innerhalb der Function oder Subroutine) zu Verfügung
unreserve
Vor dem "Return" der Subroutine oder Function muß natürlich alles wiederhergestellt werden BasCom hat natürlich mitgezählt, wieviel Platz benötigt wurde, und er weiß auch, wieviele solcher Adressen er auf den Soft-Stack gelegt hat.
….. ADIW YL,$0002 // Addieren auf den Software Stack Pointer LDI r24,$01 // Subtrahieren vom Frame Pointer (z.b. 1 Byte ) CALL SubR4 RET // return Sub or Function
SubR4: SUB r4,r24 CLR r24 SBC r5,r24 RET
Call Sub & Function
Die Parameter an die Funktion / Sub werden über den Softstack übergeben. Außer für den eigentlichen CALL der Function / Sub wird der HW-Stack hier nicht verwendet.
Es gibt an sich zwei Übergabe-Varianten: BYVAL und BYREF, es wird aber immer BYREF (Addresse von) verwendet, der Unterschied liegt nur darin, dass bei BYVAL die Addresse einer Daten-Kopie statt des Originals übergeben wird. Die Reihenfolge ist von links nach rechts, wobei die Adresse des Ergebnisses (Funktion) als erstes auf den Soft-Stack gelegt wird wird.
Folgenden Deklarationen führen im Programm zum gleichen Code
Declare Function MyFunc (byval Op1 as byte, byval Op2 as byte) as byte Declare Sub MySub (byref Result as byte , byval Op1 as byte, byval Op2 as byte)
Die Situation beim Aufruf der Funktion / Sub sieht nun folgendermaßen aus, den HW-Stack nicht berücksichtigend
Die Funktion / Sub findet nun (beim Entry)
OP2 auf Y + 0/1 OP1 auf Y + 2/3 Result auf Y + 4/5
Verwendet die Funktion / Sub nun selbst den SW-Stack oder das Frame, muß sie das natürlich bei den Y-Offsets berücksichtigen und vor dem Return muß der obige Zustand auch wiederhergestellt werden.