# in ein Schieberegister per Pointer zugreifen



## Perfektionist (15 August 2008)

so, jetzt hat es mich wieder: Das Thema big und little endian. S7 ist ja bekanntlich ein big-endian-System - aber leider nicht innerhalb der Bytes, was die Bit-Nummerierung anbetrifft.

erstens die Philosophiefrage: ist links- oder rechts-Schieben die positive Schieberichtung?

zweitens:
angenommen, mein Schieberegister ist das MD16 und ich würde mich für links-Schieben (SLD) entscheiden. Dann wäre mein erstes Bit an der Stelle M19.0 (Schieberegister-Eingang, Bit Nummer Null). Und das wird dann auf M19.1 weitergeschoben. Der Übertrag erfolgt dann von M19.7 auf M18.0.

wenn ich nun

```
L #Parameter_Zugriffsindex
LAR1
U M[ar1,p#16.0]
```
schreib, dann geht der Zugriff wegen des big endian bunt durcheinander - wäre es eine little endian Maschine, käm alles schön der Reihe nach.

was tun, damit danach noch einer durchblickt und der Zusammenhang Indexnummer und Schieberegisterplatz deutlich wird?


----------



## Pizza (15 August 2008)

Hi Perfektionist

ob links- oder rechtsschieben ist, wie du schon bemerkt hast, reine Ansichtssache 


Ich bevorzuge die Variante mit dem Rechtsschieben.
Bei uns kommen oft Schieberegister mit mehreren Doppelwörtern zum Einsatz.

Speziell geht es um Positionsverfolgung von Produkten auf Laufbändern
D.h. für jedes Band gibt es einen DB(Schiebe-DB)

Um jetzt zu wissen, ob ein am Anfang des Bandes detektiertes Produkt Position X erreicht hat, muss ich den Index jedesmal neu berechnen.
Über diesen Index greife ich dann per indirekte Adressierung auf den DB zu.

Hier hatte ich schon mal dazu geschriebn.

http://www.sps-forum.de/showthread.php?p=110069#post110069

Gruß

Pizza


----------



## Hartmut Lux (15 August 2008)

Ganz einfach, wie bei jeder Zahl welche Du schreibst ist die kleinste Ziffer rechts.

Pointer im Dword-Format beinhalten die Bitadresse, Byteweise linear gerechnet. Wenn Du indirekt auf einen geschobenen Wert Zugreifen möchtest, sind vorher die Bytes zu sortieren.

1 Bit Linksschieben heist "mal" 2 rechnen, rechtsschieben durch 2 dividieren. 
Da die Bits innerhalb des Datentypes geschoben werden sollte man wissen wie der Datentyp aufgebaut ist (im Editor F1 drücken und mal nach Datentyten suchen).

Beim Schieben eines Dword ist zu Beachten, daß bei diesem Datentyp zuerst das High- und dann das Low-Word kommen in denen das Highbyte jeweils zuerst steht.

Z.B. bei Deinem Beispiel ist

MB19 das niederwertigste Byte 
und M19.0 das niederwertigste (ganz rechts stehende) Bit, welches beim links schieben mit jedem Schritt immer weiter Richtung Bit M16.7 (Highbyte im Highword)wandert.

 Gegenfrage: was ist eine positive Schieberichtung wenn es sich nicht ums Auto handelt?


----------



## Perfektionist (15 August 2008)

Hartmut Lux schrieb:


> ... was ist eine positive Schieberichtung wenn es sich nicht ums Auto handelt?


genau das ist die Frage: gibt es eine bevorzugte Schieberichtung?

@ Pizza: Danke, das trifft es schon sehr genau. Das Kaskadieren mit dem Rotierbefehl ist sehr gut - die Berechnung des Zeigers ... na ja, im Prinzip war mir das ja schon in etwa so klar, ich scheue den Aufwand noch etwas, aber prinzipiell kopier ich das jetzt erstmal so von Dir.


----------



## Pizza (15 August 2008)

Perfektionist schrieb:


> ... aber prinzipiell kopier ich das jetzt erstmal so von Dir.


 
gerne, wenn ich auch mal helfen konnte 

Gruß

Pizza


----------



## Perfektionist (18 August 2008)

*ich glaub, ich habs*

von den drei Bit-Adressen brauch ich einfach nur das Einer-Komplement - und schon hab ich linear fortlaufend die Bitnummern des Schieberegisters:

```
L     #P_Platz_SRG
      XOD   DW#16#7
      LAR1  
      U     M [AR1,P#16.0]
```


----------



## Pizza (18 August 2008)

hi Perfektionist

nun musste ich erstmal zweimal lesen.

was sollte mir dieser Vierzeiler sagen 

nach ein bischen Grübeln, schien es mir zu dämmern.
(ist nicht so einfach mit dem Denken nach einem scheiß Tag)

schnell meine Test- und Spiel-CPU angeschmissen und siehe da,
warum einfach, wenns auch umständlich geht 

warum habe ich nur meine Schieberegisteradresse bisher so umständlich berechnet, wenn es doch so einfach geht 

Dreimal darfst du raten, wer jetzt welchen Code kopiert 

Gruß

Pizza


----------



## Perfektionist (19 August 2008)

@Pizza: Danke fürs Testen



Pizza schrieb:


> ...
> was sollte mir dieser Vierzeiler sagen
> ...


also schreib ich noch was (auch für die Mitleser) zur Erläuterung dazu:
ich hab mich nun auch (wie Pizza) erstmal für Rechtsschieben entschieden, also von Byte mit kleiner Ordnungsnummer zu Byte mit hoher Ordnungsnummer (im konkreten Fall MD16). Leider schiebt es aber dabei innerhalb des Bytes von hoher Bitnummer Richtung niederer Bitnummer. Um also die 32 Bit des Schieberegisters fortlaufend zu adressieren muss dem Pointer-Aufbau ...bbbbxxx (b=Byte, x=Bit) entsprechend also auf die Bitnummern 7, 6, ..., 1, 0, 15, 14, ..., 9, 8, 23, ... usw. zugegriffen werden.
Diesen Kunstgriff, die Zählung 7-0, 15-8, 23-16 und 31-24 umzudrehen, erledigt die Operation XOD DW#16#7, indem das Einerkomplement der Bits zwei bis null, also der drei niederwertigsten Bits des Zeigers gebildet wird und damit die Zählung dann fortlaufend erscheint.


----------



## Perfektionist (20 August 2008)

und da ich das ja gerne sauber programmieren möchte, wäre da doch ein symbolischer Zugriff auf das Schieberegister wünschenswert. Aber Siemens treibt mich da zum Wahnsinn 

was ja jederzeit geht:

```
L P##Schieberegister
```
 
was ja seltsamer Weise nicht geht

```
L P#"Schieberegister"
```
 
und was überhaupt nicht geht (weder noch!):

```
... [AR1,P##Schieberegister]
 ... [AR1,P#"Schieberegister"]
```
 
was bleibt also? gezwungener Maßen das Schieberegister in statische Lokaldaten legen und den Adressoffset auch noch von Hand rechnen? Wozu ist dieser Adressoffset beim Operanden [AR1,P#xxx.x], wenn ich da eh nichts symbolisch eintragen kann und daher P#0.0 eintrage, um zuvor per L P##... die Adresse zu ermitteln und dann selber aufzuaddieren?


----------



## Larry Laffer (20 August 2008)

Hallo Perfektionist,
der Offset hinter dem AR-Register ist eine Konstante ...!
Ich benutze das (wenn ich mal so programmiere) z.B. bei Schleifen, wo ich etwas mit dem Operanden an Adresse AR1,P#0.0 mache und den dann vielleicht in den Operanden an Adresse AR1,P#16.0 zurückschreibe - also wenn du über das entsprechend Grund-Offset ggf. 2 oder Mehr Varaiblen erreichen kannst ... (leider habe ich gerade keinen schönen Anwendungsfall parat).

Gruß
LL


----------



## volker (20 August 2008)

Larry Laffer schrieb:


> (leider habe ich gerade keinen schönen Anwendungsfall parat).


genau.
ein beispiel wäre z.b. hier ganz unten.


----------



## Perfektionist (21 August 2008)

volker schrieb:


> genau.
> ein beispiel wäre z.b. hier ganz unten.


Hallo Volker,
da hast Du mir irgendwie den falschen Link gegeben:








Larry Laffer schrieb:


> Hallo Perfektionist,
> der Offset hinter dem AR-Register ist eine Konstante ...!
> ...


genau - und P##Lokalvariable ist ein Pointer auf die die lokale Variable mit dem Namen #Lokalvariable - und damit m.E. zum Zeitpunkt der Codegenerierung (Übersetzung) eine Konstante


----------



## Larry Laffer (21 August 2008)

Perfektionist schrieb:


> genau - und P##Lokalvariable ist ein Pointer auf die die lokale Variable mit dem Namen #Lokalvariable - und damit m.E. zum Zeitpunkt der Codegenerierung (Übersetzung) eine Konstante


 
Nein,
eine Lokalvariable ist schon von Haus aus keine Konstante ... und wird auch nie als solche behandelt ...

Gruß
LL


----------



## Perfektionist (21 August 2008)

Der Inhalt der Variablen, der ist, wie der Name sagt, variabel. Die Adresse, an der dieser Inhalt steht, ist aber während der Laufzeit (Programmausführung) konstant.


----------



## Perfektionist (25 August 2008)

Da ist mir doch gerade ein Codeschnipsel über den Weg gelaufen:

```
//  Schieberegister kopieren
 
      L     #SREGISTER                  // Kopieren in TEMP-Variable und
      T     #COPY_SREG                  // Zeiger auf Adresse vom Schieberegister
      LAR1  P##COPY_SREG                // ins Adressregister 1 laden
 

// Schieberegisterbit ermitteln
 
      L     #PLATZNUMMER                // Platznummer mit Zahl 7
      L     7                           // auf größer vergleichen.
      >I                                // Wenn Platznummer zwischen
      SPB   MG07                        // 0-7 dann addiere die Zahl
      +AR1  P#3.0                       // 3 in die BYTE-Adresse vom 
      L     #PLATZNUMMER                // Adressregister 1.
      T     #SCHLEIFE                   // Die Schleife mit Wert von
      SPA   AKTI                        // Platznummer belegen.
 
MG07: L     #PLATZNUMMER                // Wenn Platznummer zwischen
      L     15                          // 8-15 dann addiere die Zahl
      >I                                // 2 in die BYTE-Adresse vom
      SPB   MG15                        // Adressregister 1.
      +AR1  P#2.0                       // Die Schleife ermittelt sich
      L     #PLATZNUMMER                // aus dem Wert in Platznummer
      L     8                           // minus 8.
      -I    
      T     #SCHLEIFE
      SPA   AKTI
 
MG15: L     #PLATZNUMMER                // Wenn Platznummer zwischen
      L     23                          // 16-23 dann addiere die Zahl
      >I                                // 1 in die BYTE-Adresse vom
      SPB   MG23                        // Adressregister 1.
      +AR1  P#1.0                       // Die Schleife ermittelt sich
      L     #PLATZNUMMER                // aus dem Wert in Platznummer
      L     16                          // minus 16.
      -I    
      T     #SCHLEIFE
      SPA   AKTI
 
MG23: L     #PLATZNUMMER                // Wenn Platznummer zwischen
      L     31                          // 24-31 dann bleibt das 
      >I                                // Adressregister 1 unverändert.   
      BEB                               // Die Schleife ermittelt sich
      L     #PLATZNUMMER                // aus dem Wert in Platznummer
      L     24                          // minus 24.
      -I    
      T     #SCHLEIFE
 
AKTI: L     #SCHLEIFE                   // Jetzt wird die BIT-Adresse
      L     0                           // vom Adressregister 1 so oft
      <=I                               // erhöht wie die
      SPB   END2                        // Anzahl der zuvor ermittelten
      +AR1  P#0.1                       // Schleifendurchläufe.
      L     #SCHLEIFE
      DEC   1
      T     #SCHLEIFE
      SPA   AKTI
 
END2: NOP   0
```
mit ein wenig Erstaunen nehme ich "LAR1  P##COPY_SREG" zur Kenntnis - die Hilfe zu AWL kennt diesen Befehl mit einer Konstanten als Operanden nicht


----------



## Larry Laffer (25 August 2008)

Erstaunen ?
Das verstehe ich nicht ... du lädst hier die Quell-Adresse der Variablen ins AR1-Register (also den Pointer auf die Variable). Dieser "Trick" ist hier im Forum schon öfter mal angewendet worden (ich glaube am liebsten von Kai) - gerne in Verbindung mit Schleifen.


----------



## Perfektionist (25 August 2008)

Perfektionist schrieb:


> ...
> mit ein wenig Erstaunen nehme ich "LAR1 P##COPY_SREG" zur Kenntnis - die Hilfe zu AWL kennt diesen Befehl mit einer Konstanten als Operanden nicht


 
... jedenfalls nicht, wenn man auf diesem Befehl F1 betätigt - wenn man dann weiterblättert in der Hilfe geht einem ein Licht auf. Ich weiß nicht warum - aber ich war irgendwie der Meinung, dass der Datenaustausch von/zum AR ähnlich eingeschränkt ist, wie der Datentrasfer von/zum STW.

und ich raufe mir weiter meine Haare:


```
LAR1 P#M100.0  // geht
 
LAR1 P#"Merkersymbol" // geht nicht
```
 
... aber ein wenig sehe ich das insofern ein, da ich ja immerhin ein UDT-Schieberegister von übergeordneter Instanz zu untergeordneter weiterreichen und zurückgeben kann und Siemens mir den Zugriff


```
LAR1 P##userdefined_SRG // geht
```
 
erlaubt ...


----------

