amiga-news ENGLISH VERSION
.
Links| Forum| Kommentare| News melden
.
Chat| Umfragen| Newsticker| Archiv
.

amiga-news.de Forum > Programmierung > Structs im Speicher [ - Suche - Neue Beiträge - Registrieren - Login - ]

-1- 2 [ - Beitrag schreiben - ]

30.03.2004, 18:07 Uhr

Ralf27
Posts: 2779
Nutzer
Ich verfolge denn C-Kurs und bei denn Strukts kam es bei mir zu einem "Aha"-Erlebniss.

Jetzt möchte ich aber meine alten Basic-Projekte nicht sterben lassen bzw. ist es fast unmöglich sie in C zu neu zu schreiben.

Deswegen folgende Frage:
Wenn ein Programm ein Strukt zurückliefert das z.b. wie folgt aufgebaut ist, wie kann ich dann mit Basic drauf zugreifen?

struct test
{
struct bla
struct bla2
...
}

struct bla
{
ULONG info
...
}

...

Wie kann ich dann am besten auf die Daten zurückgreifen? Ich nehme mal folgendes an:

Anfangbla=peekl(test)
Anfangbla2=peekl(test+4)
Info=peekl(Anfangbla)

Kommt das so in etwa hin?

Wie werden also Structs im Speicher abgelegt?
--
http://www.alternativercomputerclub.de.vu

[ - Antworten - Zitieren - Direktlink - ]

30.03.2004, 18:15 Uhr

Holger
Posts: 8116
Nutzer
Habe gerade im anderen Thread geantwortet...
http://www.amiga-news.de/forum/thread.php3?id=9759&start=112&BoardID=7


mfg
--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

30.03.2004, 18:35 Uhr

obw
Posts: 94
Nutzer
Zitat:
Original von Ralf27:

[snip]
Wie werden also Structs im Speicher abgelegt?


Die Antwort wird dir nicht gefallen: Das ist implementierungsabhängig. Und wer schon mal in den C-Standard geguckt hat, wird jetzt tief Luft holen. :rotate:

Vorgegeben ist nur:

  • Die Startadresse der Struktur ist die Startadresse der ersten Komponente.
  • In der Reihenfolge der Deklarationen stehen die Komponenten auch in der Struktur.


Ob da noch irgendwelche Füllbytes drin sind, oder wie gar Bitfelder implementiert sind, das ist völlig von der Maschine und dem Compiler abhängig. Das kann man also nur im Einzelfall (z.B. gcc 3.3 auf m68k) sagen. Muß man dann durch Ausprobieren rausfinden, z.B. durch:

code:
struct foo bar;
char *baz = (char *)bar;
for (i = 0; i< sizeof (struct foo); i++, baz++) {
  /* *baz ist der Inhalt eines Strukturbytes.
   * mach was draus ;-)
   */
  ...
} /* Diese Schleife ist die einzelnen Bytes der Struktur
   * durchgeeiert. Jetzt wissen wir, ob die Struktur Löcher hat
   * und vielleicht sogar, wie rum die CPU ihre Wörter sortiert.
   */


Naja, aber ich hoffe, das Prinzip kommt rüber. ;)

OBW

[ - Antworten - Zitieren - Direktlink - ]

30.03.2004, 21:37 Uhr

Ralf27
Posts: 2779
Nutzer
Hm, doch nicht so einfach wie ich dachte. Da hilft also nur Testen?
--
http://www.alternativercomputerclub.de.vu

[ - Antworten - Zitieren - Direktlink - ]

30.03.2004, 21:57 Uhr

Mad_Dog
Posts: 1944
Nutzer
Ich versteh nicht so recht, für was Du das brauchst. :dance3:

In C kannst Du doch ganz bequem mit MeineStruktur.SeineKomponente bzw. MeinZeiger->KomponenteDerStruktur auf die Komponente Zugreifen.

In BASIC gibt es sowieso keine Strukturen. Also worüber verbrichst Du Dir bitte den Kopf? Wenn Du in Deinen alten BASIC-Programmen, die Du nach C umschreiben möchtest, in komplizierter Low-Level Manier auf irgendwelche Strukturen des AmigaOS zugegriffen hast, dann kannst Du das in C (wie oben erwähnt) ganz einfach haben, ohne die Adressen zu berechnen - wie auch Holger in dem anderen Thread geschrieben hat.

--

http://www.norman-interactive.com

[ - Antworten - Zitieren - Direktlink - ]

30.03.2004, 23:15 Uhr

Ralf27
Posts: 2779
Nutzer
Zitat:
Original von Mad_Dog:
Ich versteh nicht so recht, für was Du das brauchst. :dance3:

In C kannst Du doch ganz bequem mit MeineStruktur.SeineKomponente bzw. MeinZeiger->KomponenteDerStruktur auf die Komponente Zugreifen.

In BASIC gibt es sowieso keine Strukturen. Also worüber verbrichst Du Dir bitte den Kopf? Wenn Du in Deinen alten BASIC-Programmen, die Du nach C umschreiben möchtest, in komplizierter Low-Level Manier auf irgendwelche Strukturen des AmigaOS zugegriffen hast, dann kannst Du das in C (wie oben erwähnt) ganz einfach haben, ohne die Adressen zu berechnen - wie auch Holger in dem anderen Thread geschrieben hat.

--

http://www.norman-interactive.com


Ich dachte ich hätte das schon geschrieben:
Ich hab bis jetzt alle Projekte in Basic(telweise mit ASM-Unterstützung) geschrieben. Und diese möchte ich halt hier und da beenden und nicht gerade komplett in C umschreiben.

Jetzt gibt es einen Befehl in einer Library die ein Struct zurückliefert denn ich gerne auslesen möchte mit Basic. Wenn es nicht geht...ok, wenn es geht, um so besser! Ich möchte es halt versuchen.


Mir ist klar das ich mit C weiter komme.



Achja, wegen Strukturen: Ok, in Amiga- oder MaxoncBasic gibt es da nicht. Da hab ich halt einfach Felder genommen, was der Sache auch sehr nahe kommt, aber was nicht das gleiche ist (ist mir schon klar).

BlitzBasic kennt übrigens Strukturen... :)



--
http://www.alternativercomputerclub.de.vu

[ - Antworten - Zitieren - Direktlink - ]

31.03.2004, 09:30 Uhr

thomas
Posts: 7716
Nutzer
Zitat:
Original von Ralf27:
Hm, doch nicht so einfach wie ich dachte. Da hilft also nur Testen?
--
http://www.alternativercomputerclub.de.vu



Blödsinn. Vergiß alles, was die anderen schreiben. Die Elemente der Structs stehen einfach hintereinander im Speicher. Nur, wenn ein Wort (short, int, long oder pointer) auf einer ungeraden Adresse landet, dann wird davor ein Byte eingefügt, damit die Adresse wieder gerade wird.

Allerdings war deine Frage schon falsch. Es gibt keine Funktion, die eine Struct zurückgibt. Wenn eine Funktion eine Struct angelegt hat, dann gibt sie einen Pointer darauf zurück (also die Adresse der struct, nicht die struct selbst). Deshalb ist auch der Einwand von Holger überflüssig: wenn eine Struct einen Pointer enthält, dann steht da selbstverständlich nur der Pointer (also die Adresse mit 4Bytes) und nicht die Struct selber.

Es gibt in C auch das Makro offsetof(), womit man den Offset eines Datenelements in einer Struktur herausfinden kann.

Wenn es das nicht gibt kann man es ungefähr so definieren:

#define offsetof(element,pointer) ((char *)(&(pointer)->(element)) - (char *)(pointer))

Beispiel:

struct Screen *scr;
printf ("offset of Width = %dn",offsetof(Width,scr));
printf ("offset of RastPort = %dn",offsetof(RastPort,scr));
printf ("offset of TxBaseline = %dn",offsetof(RastPort.TxBaseline,scr));

Die ganzen Einwände über Architekturabhängigkeit und so gelten nur, wenn man portierbar programmieren möchte. Um ClassicAmiga-C mit ClassicAmiga-Basic zu verbinden, ist das alles relativ einfach.

Gruß Thomas
--
Email: thomas-rapp@web.de
Home: home.t-online.de/home/thomas-rapp/

[ - Antworten - Zitieren - Direktlink - ]

31.03.2004, 10:08 Uhr

Solar
Posts: 3680
Nutzer
Zitat:
Original von thomas:
Blödsinn. Vergiß alles, was die anderen schreiben.


Jetzt kommt der Fachmann.

Zitat:
Die Elemente der Structs stehen einfach hintereinander im Speicher. Nur, wenn ein Wort (short, int, long oder pointer) auf einer ungeraden Adresse landet, dann wird davor ein Byte eingefügt, damit die Adresse wieder gerade wird.

Das mag so sein, muß aber nicht - nicht einmal für alle 68k-Compiler, und schon gar nicht für alle Compiler.

Zitat:
ISO/IEC 9899:1999(E), 6.7.2.1, Absatz 12f.:

Each non-bit-field member of a structure or union object is aligned in an implementation-defined manner appropriate to its type.

[..]

There may be unnamed padding within a structure object, but not at its beginning.


Zitat:
Es gibt in C auch das Makro offsetof(), womit man den Offset eines Datenelements in einer Struktur herausfinden kann.

Ja, und zwar im Header <stddef.h>.

Zitat:
Die ganzen Einwände über Architekturabhängigkeit und so gelten nur, wenn man portierbar programmieren möchte. Um ClassicAmiga-C mit ClassicAmiga-Basic zu verbinden, ist das alles relativ einfach.

Du gehst fröhlich davon aus, das alle 68k-Compiler - insbesondere der von Ralf27 - 16-bit-Alignment benutzt, was mitnichten vorgeschrieben ist.

Zitat:
GCC 3.3 Manual, M680x0 Options:

-malign-int
-mno-align-int


Control whether GCC aligns int, long, long long, float, double, and long double variables on a 32-bit boundary (-malign-int) or a 16-bit boundary (-mno-align-int). Aligning variables on 32-bit boundaries produces code that runs somewhat faster on processors with 32-bit busses at the expense of more memory.

Warning: if you use the -malign-int switch, GCC will align structures containing the above types differently than most published application binary interface specifications for the m68k.


Nicht anderer Leute Aussagen Blödsinn schimpfen, wenn Du Dir nicht 100% sicher bist.

[ Dieser Beitrag wurde von Solar am 31.03.2004 editiert. ]

[ - Antworten - Zitieren - Direktlink - ]

31.03.2004, 10:52 Uhr

whose
Posts: 2156
Nutzer
Wenn ich den Ralf richtig verstanden habe, geht es ihm um eine Struktur, die von einer OS-Funktion zurückgeliefert wird, richtig? Da ist es in der Tat wurscht, was ein C-Compiler machen _würde_. Wenn man sich die entsprechenden struct Deklarationen in den RKMs anschaut, sieht man, daß die Struktur-Member tatsächlich platt hintereinander im Speicher liegen und _nur wenn es notwendig ist_ ein Pad-Byte eingefügt wird. Diese sind dann natürlich als struct-Member in der Deklaration vorhanden.

Da kann der Ralf also wirklich ganz simpel aus dem Speicher lesen und sich an den Deklarationen aus den RKMs oder dem NDK orientieren.

Noch ein Wort zu den Compiler-Jüngern hier:

Alignment in Strukturen findet nicht notwendigerweise statt. Nicht jeder Compiler macht das und nicht immer ist es auch erwünscht. Daher fügt der weise Programmierer die Pad-Bytes oder -Words selbst ein (so geschehen bei den OS-Funktionen). Das sollte man so oder so _immer_ tun, damit Leute wie Ralf, die nun mal _nicht_ ausschließlich in C arbeiten, nicht ins Trudeln kommen, weil sie nicht wissen _können_, ob innerhalb einer Struktur Alignment stattfindet oder nicht, wenn nur ein Compiler darüber entscheidet.

Grüße


Wolfgang

[ - Antworten - Zitieren - Direktlink - ]

31.03.2004, 11:06 Uhr

thomas
Posts: 7716
Nutzer
@Solar: schon mal was von "keep it simple" gehört ? Einem Anfänger was von ISO-Normen vorzubeten ist sicher der "richtige" Weg, Verständnis zu erreichen. Es muß nicht immer alles akademisch genau genommen werden. Meistens reichen die Regeln, ohne die Ausnahmen zu betrachten.

Gruß Thomas

--
Email: thomas-rapp@web.de
Home: home.t-online.de/home/thomas-rapp/

[ - Antworten - Zitieren - Direktlink - ]

31.03.2004, 11:06 Uhr

Solar
Posts: 3680
Nutzer
Zitat:
Original von whose:

Noch ein Wort zu den Compiler-Jüngern hier:

Alignment in Strukturen findet nicht notwendigerweise statt. Nicht jeder Compiler macht das und nicht immer ist es auch erwünscht. Daher fügt der weise Programmierer die Pad-Bytes oder -Words selbst ein (so geschehen bei den OS-Funktionen).


Noch ein Wort zu den Praktikern hier:

Die Anforderungen an das Padding von structs ändert sich, nicht nur mit der CPU-Familie, sondern ggf. schon mit der CPU-Generation (z.B. 68000 -> 68020). Womit Dein Source dann auf der neuesten CPU-Generation zwar compilen, aber zur Laufzeit dann mit einer Alignment Exception aussteigen würde. Hurra, alle struct-Deklarationen anpassen - und zwar im OS und ggf. auch im Client-Code, der sich blind darauf verlassen hat.

Dazu kommt: Es ist dem Compiler erlaubt, beliebig Paddings hinzuzufügen!

code:
struct example
{
    char c;
    char pad;
    int i;
}

size_t x = sizeof(example);


Wenn Du davon ausgehst, das x schon 6 betragen wird, bist Du auf dem Holzweg (siehe obige gcc-Option)! Es ist dem Compiler erlaubt, sonstwas für ein Padding zu verwenden, wenn's ihm gefällt. Klar, mit den falschen Settings bekommst Du Probleme mit den OS-Headern - aber auch Betriebssysteme ändern sich gelegentlich, und willst Du dann allen Code anpassen, oder einfach nur neu compilieren müssen?

(Ich bezweifle z.B., das AmigaOS 4 16-bit Alignments verwenden wird...)

sizeof() und offsetof() sind die einzigen Methoden, auf die man sich verlassen kann, selbst wenn man "nur" einen 68k betrachtet.

[ - Antworten - Zitieren - Direktlink - ]

31.03.2004, 11:09 Uhr

Solar
Posts: 3680
Nutzer
Zitat:
Original von thomas:
@Solar: schon mal was von "keep it simple" gehört ? Einem Anfänger was von ISO-Normen vorzubeten ist sicher der "richtige" Weg, Verständnis zu erreichen. Es muß nicht immer alles akademisch genau genommen werden. Meistens reichen die Regeln, ohne die Ausnahmen zu betrachten.


Was ich zitiert habe, ist die Regel, und ein fixes 16-bit Padding die Ausnahme!

Ich persönlich finde es äußerst hilfreich, wenn in einer technischen Diskussion auch die entsprechenden Verweise zitiert werden, statt sich auf "Nein!" - "Doch!" einzulassen. Außerdem hatte ich den ISO-Text gerade eh zur Hand.

Gut, in Zukunft lasse ich das, und verbleibe auf "nein" - "doch" - Niveau...

[ - Antworten - Zitieren - Direktlink - ]

31.03.2004, 12:51 Uhr

whose
Posts: 2156
Nutzer
Zitat:
Original von Solar:

Noch ein Wort zu den Praktikern hier:

Die Anforderungen an das Padding von structs ändert sich, nicht nur mit der CPU-Familie, sondern ggf. schon mit der CPU-Generation (z.B. 68000 -> 68020). Womit Dein Source dann auf der neuesten CPU-Generation zwar compilen, aber zur Laufzeit dann mit einer Alignment Exception aussteigen würde. Hurra, alle struct-Deklarationen anpassen - und zwar im OS und ggf. auch im Client-Code, der sich blind darauf verlassen hat.


Alles schön und grün. Ich sollte vielleicht ein klein bißchen was aufklären:

1. Ralfs Frage zielt ÜBERHAUPT nicht auf C-Compiler ab. Er will in BASIC arbeiten. Geht das in Deinen ANSI-ISO-POSIX-WasWeißIch-GCC-rulez-Schädel? Okay, MaxonBasic erlaubt keine direkten Zugriffe auf Strukturen, also im Zweifelsfall auf Byte- oder Word- oder Longwort-Integer-Basis arbeiten. Da ists dann für Ralf entscheidend, ob Padding in den OS-Deklarationen (deren maschinenabhängigkeit dokumentiert ist!) verwendet wurde oder in der Dokumentation des entsprechenden Programms ein Hinweis darauf zu finden ist oder nicht.

2. Wenn Du schon auf Dokumentation und Normen hinweist, dann setz Dich hin und schau Dir die AOS-Includes nochmal GANZ genau an. Da wirst Du z.B. in den Struktur-Deklarationen KEIN char oder sonstwas für Padding finden, das absolut compilerabhängig ist (Dein int z.B.). Gerade Du solltest eigentlich wissen, welchem Zweck beispielsweise das #define unsigned char UBYTE dient. Die Maschinenabhängigkeit dieser Strukturen ist eine andere Sache, aber _ich_ kann nun wahrlich nichts für die Kurzsichtigkeit der AOS-Entwickler der ersten Stunde (z.B. Word-Alignment statt Longword-Alignment in einigen wenigen Strukturen). Abgesehen davon: Seit wann arbeitet ein C-Compiler BEIM ZUGRIFF auf Strukturen, die er nicht selbst erzeugt hat, mit Padding? Wenn das so wäre, könntest mit dem GCC nicht für AOS entwickeln. Das Thema hier dreht sich nur um den Zugriff, sonst nichts.

Wenn ich mich jetzt hinsetze und progge, und ich lasse mein Programm bspw. auf nem A1 mit AOS4 compilieren, dann sollte ich mich darauf verlassen können, das solche #defines wie oben und/oder die Struktur-Deklarationen an die Gegebenheiten der jeweiligen Maschine angepaßt wurden, und mein Code steigt dann halt NICHT mit ner Alignment Exception aus. So funktioniert unter anderem maschinenunabhängiges proggen für ein _bestimmtes_ OS (also nix "Speicherverschwendung wegen generellem Longword-Alignment rulez!").

3. Dein Hinweis auf sizeof()/offsetof() in allen Ehren, aber nichts desto trotz bekomme ich aus Deiner Struktur-Deklaration genau _das, was ich haben will_(6 Bytes resp. 2 Bytes und ein Longword, kein Padding), weil ich meinen Computer/Compiler kenne. Da ich meinen Entwicklerkollegen gegenüber loyal eingestellt bin, kläre ich sie darüber auf, auf welcher Basis (16/32 Bit Integer z.B., Padding oder nicht) die Deklaration stattgefunden hat. Dann wissen sie nämlich, was sie zu tun haben. Sofern sie ihren Computer/Compiler/Assembler kennen...

@Ralf:

Schau Dir die Deklaration der betreffenden Struktur an und dann kannst versuchen, direkt auf die entsprechenden Daten zuzugreifen (den Offset zur Basis-Adresse nicht vergessen _in Bytes auszurechnen_!VORSICHT(!), wenn Du eine ungerade Adresse dabei rausbekommst. Dann hast Dich wahrscheinlich irgendwo verrechnet). Du solltest aber auch darauf achten, in welchen Variablentyp Du die Daten hineinkopierst, sonst bekommst Du Besuch vom Guru. Es ist auf dem 68K keine gute Idee, auf ungerade Adressen (Byte) zuzugreifen, wenn man das nicht auch byteweise tut.

Grüße

[ - Antworten - Zitieren - Direktlink - ]

31.03.2004, 13:31 Uhr

Ralf27
Posts: 2779
Nutzer
Erstmal danke für alle Postings.

Als erstes scheint mir es ein Problem zu geben um auf den ersten Eintrag im Struct zu kommen. Ich dachte das der Rückgabewert direkt der erste Wert im Struct, bzw. das Struct selbst zeigt. Also jetzt ohne Umrechnung.
Ich frage mich gerade was ich da umrechnen muß, bzw. wie? Wäre das dann ein BCPL-Pointer?!?(Wie schreibt man das eigentlich nochmal? Hab mit Basic damit recht wenig am Hut, hab aber mal irgendwo gelesen das im OS so einige Pointer "deklariert" sind.)

Das erklärt auch das Phänomen das ich einfach mal beim Testen was an der entsprechenden Adresse(ohne Umrechnung!) an Daten im Speicher sind und hab sie mir einfach mal 1kb als Text auf dem Bildschirm ausgeben lassen, wobei ich hin und wieder die Daten hatte und dann seltsamerweiße auch mal mein Programm. Scheint wohl daran zu liegen das mal zufälligerweiße gerade der Speicher da frei war für die LIBS-Routine und mal nicht.

So, also wie Rechne ich den Pointer um? Hab noch sowas wie 1+x:4 in Erinnerung. Muß ich ann alle Pointer im Struct so umrechnen?


Achja, wenn es mal funktioniert...
Ich hab nicht vor das Basicprogramm irgendwohin zu portieren, bzw. ist es unwahrscheinlich das sich die Libs mal ändert. Sollte es mal ne neue Version geben, dann kann ich das ja mal testen. :)


So, das ganze werde ich dann heute Abend mal testen. Bin mal gespannt.
--
http://www.alternativercomputerclub.de.vu

[ - Antworten - Zitieren - Direktlink - ]

31.03.2004, 13:34 Uhr

Solar
Posts: 3680
Nutzer
Ralf27 hat von irgendeiner Library gesprochen, die einen struct zurückliefert, den er aus einem Basic-Programm aus ansprechen will. Vom OS war in erster Näherung mal gar nicht die Rede.

Meiner Erfahrung nach führt jedes C/C++-Wissen, das ausschließlich anhand einer einzelnen Implementierung erworben wurde, früher oder später zu massiven Schwierigkeiten. Mit das wichtigste bei C/C++ ist, zu wissen, wo die Sprache "wackelig" ist.

Zitat:
Original von whose:

1. Ralfs Frage zielt ÜBERHAUPT nicht auf C-Compiler ab. Er will in BASIC arbeiten. Geht das in Deinen ANSI-ISO-POSIX-WasWeißIch-GCC-rulez-Schädel?


Pfff. Komm' mal runter. Wer hier deutlich den Ton verschärft hat - und dazu auch noch technisch falsch - war thomas.

POSIX halte ich nebenbei für die Katastrophe in Dosen, und habe an keiner Stelle davon gesprochen.

Zitat:
Da ists dann für Ralf entscheidend, ob Padding in den OS-Deklarationen (deren maschinenabhängigkeit dokumentiert ist!) verwendet wurde oder in der Dokumentation des entsprechenden Programms ein Hinweis darauf zu finden ist oder nicht.

Und es schadet in keinem Fall, zu wissen, daß das mitnichten garantiertes Verhalten ist (und u.a. auf die COmpilereinstellungen ankommt), oder?

Zitat:
Wenn Du schon auf Dokumentation und Normen hinweist, dann setz Dich hin und schau Dir die AOS-Includes nochmal GANZ genau an.

Von OS war nicht die Rede, nur von einer (beliebigen) Library, deren Strukturen durchaus abweichen können.

Zitat:
Da wirst Du z.B. in den Struktur-Deklarationen KEIN char oder sonstwas für Padding finden, das absolut compilerabhängig ist (Dein int z.B.). Gerade Du solltest eigentlich wissen, welchem Zweck beispielsweise das #define unsigned char UBYTE dient.

Damit man den darunterliegenden Datentyp nachträglich ändern kann, und ein Compilerlauf zur Anpassung ausreicht.

Zitat:
Die Maschinenabhängigkeit dieser Strukturen ist eine andere Sache, aber _ich_ kann nun wahrlich nichts für die Kurzsichtigkeit der AOS-Entwickler der ersten Stunde (z.B. Word-Alignment statt Longword-Alignment in einigen wenigen Strukturen).

Angesichts der Tatsache, das sys/types.h deutlich älter ist als z.B. stdint.h, kann man "Kurzsichtigkeit" wohl kaum unterstellen. Das AmigaOS aus einem Guß wäre, hat wohl auch nie jemand behauptet, der auch nur flüchtig an der dos.library vorbeigeguckt hat.

Zitat:
Abgesehen davon: Seit wann arbeitet ein C-Compiler BEIM ZUGRIFF auf Strukturen, die er nicht selbst erzeugt hat, mit Padding?

Au, au, au... :(

Woher kennt ein Compiler das Memory-Layout einer Struktur? Richtig, aus dem Header. Wer interpretiert den Header? Genau, der aktuelle Compiler mit seinen aktuellen Einstellungen. Was passiert, wenn ein auf 32-bit-Padding eingestellter Compiler versucht, eine mit 16-bit-Padding compilierte Struktur anzufassen? Genau, undefined behaviour...

Zitat:
Wenn das so wäre, könntest mit dem GCC nicht für AOS entwickeln.

Nur wenn man die Optionen richtig einstellt...

Zitat:
Das Thema hier dreht sich nur um den Zugriff, sonst nichts.

Und gerade weil das Wissen um diesen Zugriff so schwammig ist, halte ich es für angemessen, hier vom Standard, von Compilereinstellungen etc. zu reden, denn sowohl Du als auch thomas sind hier auf dem Holzweg.

Zitat:
Wenn ich mich jetzt hinsetze und progge, und ich lasse mein Programm bspw. auf nem A1 mit AOS4 compilieren, dann sollte ich mich darauf verlassen können, das solche #defines wie oben und/oder die Struktur-Deklarationen an die Gegebenheiten der jeweiligen Maschine angepaßt wurden...

Kannst Du aber nicht! Davon rede ich hier doch... die #defines und struct-Definitionen helfen Dir nicht weiter!

Zitat:
So funktioniert unter anderem maschinenunabhängiges proggen für ein _bestimmtes_ OS (also nix "Speicherverschwendung wegen generellem Longword-Alignment rulez!").

*stöhn*

Selbst mit generellem Longword-Alignment bist Du nicht maschinenunabhängig...

Zitat:
Dein Hinweis auf sizeof()/offsetof() in allen Ehren, aber nichts desto trotz bekomme ich aus Deiner Struktur-Deklaration genau _das, was ich haben will_(6 Bytes resp. 2 Bytes und ein Longword, kein Padding), weil ich meinen Computer/Compiler kenne.

Ah! Also doch Compilerabhängig!

Zitat:
Da ich meinen Entwicklerkollegen gegenüber loyal eingestellt bin, kläre ich sie darüber auf, auf welcher Basis (16/32 Bit Integer z.B., Padding oder nicht) die Deklaration stattgefunden hat. Dann wissen sie nämlich, was sie zu tun haben. Sofern sie ihren Computer/Compiler/Assembler kennen...

Und eben davon habe ich hier gesprochen, statt einfach zu behaupten, structs würden immer 16-bit-aligned...

Zitat:
@Ralf:

Schau Dir die Deklaration der betreffenden Struktur an...


*nochmalstöhn*

...und die Padding-Einstellungen der entsprechenden Bibliothek, die wahrscheinlich 16-bit beträgt, aber auch abweichen kann...

[ - Antworten - Zitieren - Direktlink - ]

31.03.2004, 13:39 Uhr

Solar
Posts: 3680
Nutzer
Zitat:
Original von Ralf27:

Als erstes scheint mir es ein Problem zu geben um auf den ersten Eintrag im Struct zu kommen. Ich dachte das der Rückgabewert direkt der erste Wert im Struct, bzw. das Struct selbst zeigt. Also jetzt ohne Umrechnung.


Das ist auch so.

Zitat:
Ich frage mich gerade was ich da umrechnen muß, bzw. wie? Wäre das dann ein BCPL-Pointer?!? (Wie schreibt man das eigentlich nochmal? Hab mit Basic damit recht wenig am Hut, hab aber mal irgendwo gelesen das im OS so einige Pointer "deklariert" sind.)

BPTR und BSTR, wenn ich mich richtig erinnere - eigentlich nur im Umgang mit der DOS-Library. C numeriert Speicher in char's, BCPL in (Lang-?) Worten. Ich hab' das Guru Book gerade nicht zur Hand...

Zitat:
So, also wie Rechne ich den Pointer um? Hab noch sowas wie 1+x:4 in Erinnerung. Muß ich ann alle Pointer im Struct so umrechnen?

Leg' doch einfach mal dar, um welchen struct es eigentlich geht...

[ - Antworten - Zitieren - Direktlink - ]

31.03.2004, 15:30 Uhr

thomas
Posts: 7716
Nutzer

BPTR (kurz für BCPL-Pointer) mußt du mit vier multiplizieren, um die Adresse zu bekommen.

BSTR (kurz für BCPL-String) mußt du zuerst mit 4 multiplizieren, damit du an die Adresse des Strings kommst und dann steht im ersten Byte die Länge und danach der eigentliche Text. Achtung: BCPL-Strings sind nicht unbedingt mit 0 abgeschlossen, du mußt also immer das Längen-Byte beachten.

Das ganze gilt, wie schon erwähnt, nur für Strukturen der dos.library. Überall sonst werden normale Byte-Adressen benutzt, die man nicht umrechnen muß.

Gruß Thomas

--
Email: thomas-rapp@web.de
Home: home.t-online.de/home/thomas-rapp/

[ - Antworten - Zitieren - Direktlink - ]

31.03.2004, 22:02 Uhr

Ralf27
Posts: 2779
Nutzer
Hm, Structs.... nunja, ich hab es wohl raus. Hab zwar noch nicht alle Daten erreicht die dieser Struct liefert, aber das wird noch. Hab halt nur ein paar Stellen versucht und es hat funktioniert.

Hä, wäre doch gelacht wenn das ein alter "Basicer" eine C-Struct nicht zerlegen könnte. :D

Danke!

PS: Werd da noch einige Zeit lang am Struct kabbern...
--
http://www.alternativercomputerclub.de.vu

[ - Antworten - Zitieren - Direktlink - ]

31.03.2004, 23:09 Uhr

Ralf27
Posts: 2779
Nutzer
Ha, ging jetzt doch schneller als ich dachte. Hab jetzt alle für mich interesanten Daten "extrahiert" und was soll ich tippen.. es funktioniert. :dance2:

Hin und wieder sieht man halt den Wald vor lauter Bäumen nicht. :)
--
http://www.alternativercomputerclub.de.vu

[ - Antworten - Zitieren - Direktlink - ]

01.04.2004, 04:22 Uhr

whose
Posts: 2156
Nutzer
@Solar:

Nochmal: Schau Dir die Includes genau an. In einigen Strukturen sind Pad-Bytes als Member enthalten. Daher ist die Lage der einzelnen Struktur-Member im Speicher sehr genau festgelegt. Unter anderem dienen zu dieser Festlegung die Restriktionen der Maschine (68K).

An diesen Restriktionen hängt die Erzeugung des Codes durch den Compiler. Hält der sich nicht daran, _kann_ ein Programm auf dieser Maschine nicht funktionieren, wenn es auf extern erzeugte "Strukturen" zugreift. Normalerweise sollte der GCC auf die Restriktionen der Maschine Rücksicht nehmen. Von meiner Version weiß ich, daß sie es tut. Weil ich den StormC4-GCC kenne.

Insofern sind einige Dinge schon compilerabhängig, da hast Du Recht. Wenn aber der Compiler Bockmist baut, ist auch der Bockmist vom Compiler abhängig, oder nicht? Dann nehme ich einen, der das Gewünschte tut.

Ich hab die Longword-Alignment-Option nie getestet, weil ich für AOS nie Longword-Alignment gebraucht habe (wozu auch?). Im schlimmsten Fall sollte er meckern, daß diese Option für die Maschine nicht taugt (Word-Alignment beim 68K), im günstigsten Fall sollte er den Wunsch nach Longword-Alignment ganz einfach ignorieren.

Bei den Strukturen des AOS, die mit Padding versehen sind, hat er auch nie gemeckert. Komischerweise kam auch das AOS immer mit solchen Strukturen klar, wenn ich den Speicher dafür via Compiler besorgt habe und den Zeiger darauf ans OS übergeben habe. Könnte das damit zusammenhängen, daß der GCC hier ganz einfach kein Alignment vornimmt, weils nicht notwendig ist?

Warum macht ihr es den "anderen" (BASIC-Proggern z.B.) eigentlich immer so schwer? Ralf hats ja, Gott sei Dank, inzwischen hinbekommen. Und Padding scheint dabei kein großes Thema gewesen zu sein...

Grüße

[ - Antworten - Zitieren - Direktlink - ]

01.04.2004, 08:55 Uhr

Solar
Posts: 3680
Nutzer
Ich find's gut, das die Emotionen so weit abgekühlt sind, das man sich wieder dem fachlich - technischen zuwenden kann!

Zitat:
Original von whose:
In einigen Strukturen sind Pad-Bytes als Member enthalten. Daher ist die Lage der einzelnen Struktur-Member im Speicher sehr genau festgelegt. Unter anderem dienen zu dieser Festlegung die Restriktionen der Maschine (68K).


Die Restriktionen ergeben sich halt nicht nur aus der Maschine, sondern aus der Kombination CPU, Speicherbus, OS, Systemcompiler.

Zitat:
Im schlimmsten Fall sollte er meckern, daß diese Option für die Maschine nicht taugt (Word-Alignment beim 68K), im günstigsten Fall sollte er den Wunsch nach Longword-Alignment ganz einfach ignorieren.

Der Punkt ist doch, das es 68k-Maschinen gibt, auf denen Longword-Alignment durchaus Sinn macht und besagte GCC-Option auch angebracht ist. Auf AmigaOS 3.x ist es halt anders. GCC bietet beide Optionen an. Und um zu wissen, welche die Richtige ist, muß man wissen, wie die Auswirkungen sind.

Zitat:
Bei den Strukturen des AOS, die mit Padding versehen sind, hat er auch nie gemeckert. Komischerweise kam auch das AOS immer mit solchen Strukturen klar, wenn ich den Speicher dafür via Compiler besorgt habe und den Zeiger darauf ans OS übergeben habe. Könnte das damit zusammenhängen, daß der GCC hier ganz einfach kein Alignment vornimmt, weils nicht notwendig ist?

Alles eine Frage der Optionen...

Zitat:
Warum macht ihr es den "anderen" (BASIC-Proggern z.B.) eigentlich immer so schwer?

Was meinst Du? Versuch' mal, ein X-Basic-Program unter Y-Basic zum Laufen zu bringen - das ist schon ohne so Feinheiten wie Struct-Paddings übel genug...

[ - Antworten - Zitieren - Direktlink - ]

01.04.2004, 12:02 Uhr

whose
Posts: 2156
Nutzer
Moin Solar!

Zitat:
Original von Solar:
Ich find's gut, das die Emotionen so weit abgekühlt sind, das man sich wieder dem fachlich - technischen zuwenden kann!


Naja, aufregend könnte ich mich immer noch, weil wir letztendlich am Thema weit vorbei diskutieren. Aber Aufregung schadet dem Teint ;)

Zitat:
Die Restriktionen ergeben sich halt nicht nur aus der Maschine, sondern aus der Kombination CPU, Speicherbus, OS, Systemcompiler.

In erster Linie basiert die Code-Erzeugung auf den Restriktionen der Maschine (CPU/BUS). Was der Linker dann später macht, um dem OS nen Gefallen zu tun, steht auf einem anderen Blatt. Das kann sogar nachträgliches Longword-Alignment sein. Je nach Notwendigkeit.

{quote]
Der Punkt ist doch, das es 68k-Maschinen gibt, auf denen Longword-Alignment durchaus Sinn macht und besagte GCC-Option auch angebracht ist. Auf AmigaOS 3.x ist es halt anders. GCC bietet beide Optionen an. Und um zu wissen, welche die Richtige ist, muß man wissen, wie die Auswirkungen sind.
[/quote]

Soweit mir bekannt ist, kommen alle 68K-basierten Maschinen, unabhängig vom Bussystem, mit Word-Alignment klar. Von der Hardware her, meine ich jetzt. Einzige Ausnahme _könnte_ (muß aber nicht, keine Ahnung) dieser 8/16-Bit-Zwitter-68K (68009?) des SinclairQL sein. Es gibt mehrere OSs, die sich nen Dreck um abwärtskompatibilität zum 68000 kümmern und durchgängig 32 Bit nutzen. Da macht Longword-Alignment so eben gerade noch Sinn. Hardwaretechnisch ist es aber nicht notwendig und im weiteren ein Fall für den Linker.

Zitat:
Alles eine Frage der Optionen...

Ich will Dich ja jetzt nicht nerven, aber: Der StormC-GCC (2.95.2) hat gar keine Longword-Alignment-Option (gerade mal nachgeschaut). Kann sein, daß der 3.3 die hat, dann wurde aber beim 68k/aout-Backend gepfuscht. Normalerweise sollte in der "machine/target"-Abteilung des Quellcodes für GCC vermerkt werden, welche Alignment-Optionen die Zielmaschine/OS überhaupt benötigt und unterstützt (bei Codeerzeugung und/oder Linken). Entsprechend dieser Vorgaben ist dann eine Longword-Align-Option vorhanden oder auch nicht. Und Longword-Alignment gehört auf AOS-68K sicherlich nicht dazu. Macht keinerlei Sinn und ist brandgefährlich (wie ich ja schon ausführte).
Cross- oder Multi-Target-Versionen sind ein anderes Thema.

Zitat:
Was meinst Du? Versuch' mal, ein X-Basic-Program unter Y-Basic zum Laufen zu bringen - das ist schon ohne so Feinheiten wie Struct-Paddings übel genug...

Naja, stimmt wohl... aber das geht am eigentlichen Thema vorbei. Ralf hat ganz klar gesagt, was er vorhat, gefragt, ob das technisch machbar ist und es _ist_ technisch machbar. Aus eben den genannten Gründen des fixen Paddings im AOS und dem (bekannten) Umgang der Compiler mit den erwähnten Restriktionen. Es ging dabei gar nicht um zwei BASIC-Dialekte oder hypothetisches Longword-Align.

Viele hier denken viel zu sehr in Begriffen der Portabilität. Was Ralf da macht, wird sicherlich nicht eines Tages auf Linux x86 laufen, oder? Wozu also Fragen der Portabilität erörtern? Das ist irgendwo ziemlich witzlos. Abgesehen davon, daß ich nicht besonders viel davon halte, in der momentanen Situation des Amiga auf eine mögliche Portierung auf Linux o.Ä. Rücksicht zu nehmen. Man sollte erstmal wieder reichlich neue Programme für AOS (und dessen Eigenheiten) entwickeln, dann kann man immer noch darüber nachdenken, ob man diese Perlen anderen OSs zugänglich macht oder doch lieber neue Leutz für unser System gewinnt damit ;)

Grüße


[ - Antworten - Zitieren - Direktlink - ]

01.04.2004, 12:58 Uhr

Solar
Posts: 3680
Nutzer
Zitat:
Original von whose:

Soweit mir bekannt ist, kommen alle 68K-basierten Maschinen, unabhängig vom Bussystem, mit Word-Alignment klar.


Soweit Dir bekannt ist. Wenn Du ein reines 32-bit Speicherinterface hast, bedeutet ein 16-bit Zugriff wahlweise eine Performanceeinbuße oder einen Busfehler. Ich könnte mir auch vorstellen, das z.B. bestimmte Gerätetreiber ein 32-bit Padding erfordern - das Du dann entweder "handpadden" kannst, oder es dem Compiler überläßt.

Zitat:
Da macht Longword-Alignment so eben gerade noch Sinn. Hardwaretechnisch ist es aber nicht notwendig und im weiteren ein Fall für den Linker.

Öhm... der Linker kann da sehr wenig tun. Z.B. wenn ein struct "by value" übergeben wird ist die Stackbehandlung auf das Padding festgelegt, und der Linker guckt in die Röhre.

Zitat:
Ich will Dich ja jetzt nicht nerven, aber: Der StormC-GCC (2.95.2) hat gar keine Longword-Alignment-Option (gerade mal nachgeschaut).

Au, stimmt, StormC reitet ja noch den Dinosaurier...

Zitat:
Kann sein, daß der 3.3 die hat, dann wurde aber beim 68k/aout-Backend gepfuscht.

Den entsprechenden Ausschnitt aus dem 3.3-Manual habe ich oben zitiert. Eine Option anzubieten, die technisch durchaus Sinn machen kann, empfinde ich nicht als "gepfuscht". 68k wird nicht nur in Amigas, Ataris und alten Suns und Mac's verwendet...

Zitat:
Normalerweise sollte in der "machine/target"-Abteilung des Quellcodes für GCC vermerkt werden, welche Alignment-Optionen die Zielmaschine/OS überhaupt benötigt und unterstützt (bei Codeerzeugung und/oder Linken). Entsprechend dieser Vorgaben ist dann eine Longword-Align-Option vorhanden oder auch nicht. Und Longword-Alignment gehört auf AOS-68K sicherlich nicht dazu.

Das einzige noch unterstützte 68k-Target ist m68k-hp-hpux, weil sich für die übrigen 68k-Targets keine Maintainer mehr gefunden haben. Und offensichtlich macht zumindest da die Option noch Sinn, sonst wär' sie nicht mehr drin.

Zitat:
Cross- oder Multi-Target-Versionen sind ein anderes Thema.

Die CPU-spezifischen Optionen sind eben nur von der CPU abhängig, nicht vom Target.

Zitat:
Ralf hat ganz klar gesagt, was er vorhat, gefragt, ob das technisch machbar ist und es _ist_ technisch machbar. Aus eben den genannten Gründen des fixen Paddings im AOS und dem (bekannten) Umgang der Compiler mit den erwähnten Restriktionen. Es ging dabei gar nicht um zwei BASIC-Dialekte oder hypothetisches Longword-Align.

Er will nicht näher spezifizierten C-Code mit nicht näher spezifizierten BASIC-Code zusammenbringen. thomas erzählt ihm, alles egal, alles immer 16-bit aligned. Ich sag' wie's ist (ein bißchen mehr wissen hat noch nie geschadet), und verstehe nicht, wo das Problem liegt, wenn ich darauf hinweise, das 16-bit-Alignment durchaus keine Eigenschaft der Sprache C ist?!?

Zitat:
Viele hier denken viel zu sehr in Begriffen der Portabilität. Was Ralf da macht, wird sicherlich nicht eines Tages auf Linux x86 laufen, oder?

Ja, und vor AOS 2.x hat Leo Schwab auch RastPorts auf dem Stack erzeugt...

Als ob das Wissen um die Details irgendjemandem weh täte?!? Was schadet es Ralf, oder einem beliebigen anderen Mitleser hier, zu wissen, was 16-bit-Alignment eigentlich ist, das es auf AmigaOS die Regel ist, aber man sich schon auf einem anderen 68k-OS und schon gar nicht auf einem PPC-OS darauf verlassen kann?

Ob er dieses Wissen dann anwendet, um portierbar zu proggen, oder es sich zusammenhackt, ist doch immer noch seine Sache.

Zitat:
Wozu also Fragen der Portabilität erörtern?

Wozu StVO, ich fahr' seit 10 Jahren unfallfrei?

Zitat:
Das ist irgendwo ziemlich witzlos. Abgesehen davon, daß ich nicht besonders viel davon halte, in der momentanen Situation des Amiga auf eine mögliche Portierung auf Linux o.Ä. Rücksicht zu nehmen.

Gaaaaa-ha-haaa! X( Wer hat denn davon gesprochen? X(

Ich wollte klar machen, was "C" ist, was "GCC" und was "AmigaOS", und das die drei Teile mitnichten aus einem Guß sind. Ich wollte klar machen, wie structs funktionieren, und wie Compiler Alignment handhaben, statt nur zu sagen, "ungerade Adressen aufrunden".

Vielleicht schreibt Ralf sein nächstes Programm für AOS 4 / MOS?

Gut, ich halte die Backen. Man verzeihe mir, das ich eine Welt außerhalb AOS 3.x angenommen habe... :(

[ - Antworten - Zitieren - Direktlink - ]

01.04.2004, 14:43 Uhr

gni
Posts: 1106
Nutzer
Zitat:
Original von Solar:
Das einzige noch unterstützte 68k-Target ist m68k-hp-hpux, weil sich für die übrigen 68k-Targets keine Maintainer mehr gefunden haben.

Woher hast Du das? Das ist vollkommen verkehrt. hpux ist raus [mit 3.5]
Zitat:
Ja, und vor AOS 2.x hat Leo Schwab auch RastPorts auf dem Stack erzeugt...
Den kennt doch keiner von denen die hier posten ;-)


[ - Antworten - Zitieren - Direktlink - ]

01.04.2004, 15:18 Uhr

Solar
Posts: 3680
Nutzer
Zitat:
Original von gni:
Woher hast Du das? Das ist vollkommen verkehrt. hpux ist raus [mit 3.5]


Öhm... flüchtiger Blick auf gcc.gnu.org / Supported Platforms...

Von 3.3.3 gibt's successful builds für m68k-unknown-linux-gnu... und mit pre-release Versionen von GCC schlage ich mich gar nicht erst herum. ;-)



[ - Antworten - Zitieren - Direktlink - ]

01.04.2004, 16:15 Uhr

Ralf27
Posts: 2779
Nutzer
Ich hätte nicht gedacht was für eine Welle der Postings ich mit meiner Frage lostreten würde. :)

Also, das Basicprogramm ist logischerweiße nicht portierbar und ich hab es damit auch nicht vor.

Für sowas habe ich in Zukunft C. :)
--
http://www.alternativercomputerclub.de.vu

[ - Antworten - Zitieren - Direktlink - ]

01.04.2004, 16:31 Uhr

thomas
Posts: 7716
Nutzer

Das Problem ist, daß C an Universitäten gelehrt wird und dort bis zur Philosophie erhoben wird. Wenn du eine praktische Antwort haben möchtest, mußt du die Theoretiker von der Diskussion ausschließen.

Wenn du Assembler kannst, könntest du dir auch einfach vom C-Compiler die Assembler-Liste ausgeben lassen, da steht genau drin, wie er auf Felder in Strukturen zugreift. Bei DCC stehen sogar die C-Befehle als Kommentare im Assembler-Code, sodaß man die bewußten Stellen sehr schnell findet.

Gruß Thomas
--
Email: thomas-rapp@web.de
Home: home.t-online.de/home/thomas-rapp/

[ - Antworten - Zitieren - Direktlink - ]

01.04.2004, 17:09 Uhr

Solar
Posts: 3680
Nutzer
Zitat:
Original von thomas:

Das Problem ist, daß C an Universitäten gelehrt wird und dort bis zur Philosophie erhoben wird. Wenn du eine praktische Antwort haben möchtest, mußt du die Theoretiker von der Diskussion ausschließen.


Na wie gut, daß Du mich nicht meinen kannst, der ich mein C aus dem K&R bzw. dem Tutorial zu MaxxonC++3 erlernt und nie einen Universitäts-C-Kurs besucht habe. :P

Allerdings habe ich einen Hang zum Perfektionismus, was Code angeht. Mein Chef findet's bedeutend weniger schlimm als ihr hier. 8)

[ - Antworten - Zitieren - Direktlink - ]

01.04.2004, 18:15 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von thomas:
Wenn du Assembler kannst, könntest du dir auch einfach vom C-Compiler die Assembler-Liste ausgeben lassen, da steht genau drin, wie er auf Felder in Strukturen zugreift. Bei DCC stehen sogar die C-Befehle als Kommentare im Assembler-Code, sodaß man die bewußten Stellen sehr schnell findet.

Das wäre aber ziemlich umständlich. Normalerweise produziert ein Compiler keinen Code, wenn im C-source keiner ist. Dann müßtest Du ja für alle Struktureinträge, die Dich interessieren, Zugriffe erzeugen und übersetzen.

Wäre es nicht einfacher, für OS-Strukturen die in den NDKs enthaltenen Assembler-Includes zu benutzen?
Oder halt "Amiga-Intern", resp. "Profi-KnowHow". Dort sind alle dokumentierten Strukturen auch mit Offsets versehen.

mfg
--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

01.04.2004, 18:19 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von thomas:
Allerdings war deine Frage schon falsch. Es gibt keine Funktion, die eine Struct zurückgibt. Wenn eine Funktion eine Struct angelegt hat, dann gibt sie einen Pointer darauf zurück (also die Adresse der struct, nicht die struct selbst). Deshalb ist auch der Einwand von Holger überflüssig: wenn eine Struct einen Pointer enthält, dann steht da selbstverständlich nur der Pointer (also die Adresse mit 4Bytes) und nicht die Struct selber.

Lies ersteinmal richtig, bevor etwas als überflüssig bezeichnest. Meine Erklärung bezog sich auf verschachtelte Strukturen und ist selbstverständlich auch für OS-Strukturen wie z.B. in Screens eingebettete RastPorts, in events eingebettete Maus-Koordinaten oder in fast jeder Struktur anzufindene List-Header gültig.

mfg
--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]


-1- 2 [ - Beitrag schreiben - ]


amiga-news.de Forum > Programmierung > Structs im Speicher [ - Suche - Neue Beiträge - Registrieren - Login - ]


.
Impressum | Datenschutzerklärung | Netiquette | Werbung | Kontakt
Copyright © 1998-2024 by amiga-news.de - alle Rechte vorbehalten.
.