Aus RN-Wissen.de
Version vom 24. Februar 2008, 16:21 Uhr von PicNick (Diskussion | Beiträge) (Siehe auch)

(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Wechseln zu: Navigation, Suche
Rasenmaehroboter fuer schwierige und grosse Gaerten im Test

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)

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

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


LiFePO4 Speicher Test