Autor Thema: Externe Unterprogramme mit NASM  (Gelesen 30767 mal)

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #20 am: 21. April 2010, 22:34 »
Zitat
Auf was ich oben eigentlich verwiesen habe ist ld, dass Objektdateien zusammenlinkt
Also ist ld der entsprechende Jidders-CC-Befehl, oder?
Wie wärs wenn du im Archiv nachsehen würdest, wie der "Befehl" heißt? :wink:

Zitat
Etwas verwirrt bin ich schon, denn ich will ja keinen Code von Windows auf Linux oder andersherum portieren, sondern nur erreichen, dass ich mit NASM extere Unterprogramme (die auch in NASM geschrieben sind) durch Verwendung von GLOBAL und EXTERN einbinden kann.
Als Alternative kannst du auch die ganzen Assemblerdateien in einer Datei %includen, dann diese assemblieren und damit glücklich werden. Dann sparst du dir das Linken...
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

bscreator

  • Gast
Gespeichert
« Antwort #21 am: 21. April 2010, 23:03 »
Zitat
Als Alternative kannst du auch die ganzen Assemblerdateien in einer Datei %includen, dann diese assemblieren und damit glücklich werden. Dann sparst du dir das Linken...
Aber zwischen INCLUDE und externen Unterprogrammen gibt es einen großen Unterschied, aber den kennst Du mit Sicherheit.

Zitat
Wie wärs wenn du im Archiv nachsehen würdest, wie der "Befehl" heißt?
Naja, gegoogelt hab ich bereits, aber da steht fast gar nichts über Jidders drin. Bis jetzt hab ich nur das Archiv nach C:\crosstools entpackt und die PATH-Variable gesetzt.
Da Du dich aber mit Sicherheit besser als ich mit Jidders auskennst, kannst mir doch bitte ein bisl unter die Arme greifen...


Auf jeden Fall bin ich für jede Hilfe eurerseits sehr dankbar
« Letzte Änderung: 21. April 2010, 23:11 von bscreator »

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #22 am: 21. April 2010, 23:15 »
Jetzt wird ein GCC, den ich (Jidder) kompiliert habe, als "Jidders" bezeichnet... dabei weiß doch jeder, dass es mich nur einmal gibt ...

Der enthaltene Linker (und die restliche Software) ist ein 32-Bit Linker. Damit kannst du nichts anfangen.

Du kannst dir mal ALINK anschauen. Der ist laut Google als Ergänzung für NASM gedacht, und soll für 16-Bit Programme funktionieren. Ich bekomme ihn aber nicht zum laufen.

Ansonsten kannst du dir einen 16-Bit Linker von Borland oder Microsoft besorgen. Möglicherweise musst du dazu in den Paketen von Turbo C oder Visual C suchen.
Dieser Text wird unter jedem Beitrag angezeigt.

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #23 am: 22. April 2010, 00:42 »
Zitat
Als Alternative kannst du auch die ganzen Assemblerdateien in einer Datei %includen, dann diese assemblieren und damit glücklich werden. Dann sparst du dir das Linken...
Aber zwischen INCLUDE und externen Unterprogrammen gibt es einen großen Unterschied, aber den kennst Du mit Sicherheit.
Nein, den kenne ich nicht.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

bscreator

  • Gast
Gespeichert
« Antwort #24 am: 22. April 2010, 08:09 »
Zitat
Der enthaltene Linker (und die restliche Software) ist ein 32-Bit Linker. Damit kannst du nichts anfangen.
32-bit ? OK, dann werd ich den Jidder wieder ganz schnell vergessen.

Den von Borland hab ich mir auch schon runtergeladen und werd mal versuchen, ob es mit dem oder mit ALINK klappt.

Zitat
Nein, den kenne ich nicht.

Auch wenn ich das eher für einen Witz von dir halte :
Mit Include werden die Codezeilen beim Linken in den Code mit eingefügt, was bedeutet, dass das Programm größer und größer wird. Dies ist besonders im Real-Mode wegen der Segmentgrenze (glaub 64k) ziemlich schlecht.
Externe Unterprogramme bekommen jedoch eigene Segmente, wodurch die Größe des Quellcodes im Prinzip nur vom Hauptspeicher begrenzt wird.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #25 am: 22. April 2010, 09:43 »
Mit Include werden die Codezeilen beim Linken in den Code mit eingefügt
Beim Assemblieren, nicht beim Linken.

Zitat
was bedeutet, dass das Programm größer und größer wird. Dies ist besonders im Real-Mode wegen der Segmentgrenze (glaub 64k) ziemlich schlecht.
Externe Unterprogramme bekommen jedoch eigene Segmente, wodurch die Größe des Quellcodes im Prinzip nur vom Hauptspeicher begrenzt wird.
Das passiert sicher nicht automatisch. Dazu musst du den Code auch entsprechend laden, also vermutlich in deinem Bootloader. Und damit der Bootloader weiß, was er tun soll, braucht er vermutlich ein paar Informationen, wo er alles hinpacken soll. Ich glaube, mit flachen Binaries kommst du da nicht mehr sehr weit.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

bscreator

  • Gast
Gespeichert
« Antwort #26 am: 22. April 2010, 10:12 »
Zitat
Das passiert sicher nicht automatisch. Dazu musst du den Code auch entsprechend laden, also vermutlich in deinem Bootloader. Und damit der Bootloader weiß, was er tun soll, braucht er vermutlich ein paar Informationen, wo er alles hinpacken soll.

Dafür bin ich dir sehr dankbar. Hab nämlich bis jetzt gedacht, dass das irgendwie automatisch passiert (weil es so in meinem ASM-Buch steht und ich mich stur darauf verlassen hab...).

Zitat
Ich glaube, mit flachen Binaries kommst du da nicht mehr sehr weit.
Was meinst Du damit genau ?
« Letzte Änderung: 22. April 2010, 10:31 von bscreator »

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #27 am: 22. April 2010, 10:36 »
Zitat
Ich glaube, mit flachen Binaries kommst du da nicht mehr sehr weit.
Was meinst Du damit genau?
Naja, du möchtest, dass das ganze in verschiedene Segmente geladen wird, beim normalen Laden (also einfach über den BIOS-Interrupt ein paar Sektoren lesen) werden einfach die gelesenen Sektoren hintereinander in den Speicher gepackt, da wird in keinster Weise auf Segmentgrenzen geachtet. Daraus folgt, dass du irgendwie Informationen in deiner zu ladenden Datei haben musst, die dir sagen welcher Teil der Datei in welches Segment (also wohin in den Speicher) geladen werden muss. Bei ELF-Dateien gibt es dazu eine Programm-Header, die aus einer Liste von Segmenten (der Begriff Segment meint bei ELF nicht das gleiche wie im Real-Mode). Die Segmente bestehen dort jeweils aus einer physischen Basisadresse an die dieses Segment geladen werden soll, der Länge des Segments und das Offset innerhalb der Datei an dem der Code dieses Segments zu finden ist. Wenn man dann eine ELF-Datei laden will, dann wird man zuerst die Programm-Header laden (ganz am Anfang der Datei befindet die sich) und dort die ELF-Segmente durchgehen und jedes einzelne dann von dem Speichermedium laden und an die richtige Position im Arbeitsspeicher kopieren. Die Erklärung ist ist wahrscheinlich auch für andere Dateiformate in irgendeiner Weise gültig.

Zitat
Der enthaltene Linker (und die restliche Software) ist ein 32-Bit Linker. Damit kannst du nichts anfangen.
Die Idee war eigentlich ELF-Objektdateien als Input zu verwenden und das ganze als Binärdatei ausgeben zu lassen, dass sollte doch eigentlich trotzdem funktionieren, oder nicht?

Noch als kleiner Denkanstoss, den du für dich selbst beantwortet musst: Willst du wirklich Realmode? Willst du wirklich so einen Bootloader schreiben?
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

bscreator

  • Gast
Gespeichert
« Antwort #28 am: 22. April 2010, 11:47 »
Zitat
Willst du wirklich Realmode? Willst du wirklich so einen Bootloader schreiben?
Schon viele haben versucht, mich in den Protected-Mode zu bringen und wahrscheinlich habt ihr auch alle Recht, aber ich bin eben ein Sturkopf, der will, dass sein OS auch auf einem 286er noch läuft.

« Letzte Änderung: 22. April 2010, 12:22 von bscreator »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #29 am: 22. April 2010, 12:08 »
286er können auch Protected Mode. Aber okay, 16-Bit-PM ist vermutlich fast noch obskurer. ;)
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

bscreator

  • Gast
Gespeichert
« Antwort #30 am: 22. April 2010, 12:27 »
OK, dann eben auf nem 186

Geht das auch so :
1. Die 3 NASM-Quellcode-Files  (Bootloader, Kernel und UP-File) assemblieren und mit nasm -f ... zu 3 richtigen OBJ-Dateien machen
2. Mit JLOC oder dem Borland TCC diese OBJ-Files zu 3 Binarys linken
3. Diese Binarys an unterschiedliche Sektoren der Floppy schreiben, damit man den Sektor mit den ext. UPs leicht in ein anderes Segment laden kann

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #31 am: 22. April 2010, 12:43 »
2. Mit JLOC oder dem Borland TCC diese OBJ-Files zu 3 Binarys linken
Du musst zu einer Binary linken, sonst kann er beim Linken die Symbole nicht auflösen (es sei denn du willst auch noch shared-libraries - also DLL unter Windows bzw. .so unter Linux - im Bootloader haben, aber das ist zusätzlich nochmal sehr viel Aufwand).
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

bscreator

  • Gast
Gespeichert
« Antwort #32 am: 22. April 2010, 12:59 »
Aber wenn ich diese zu einer Binary linken muss, dann kann ich diese auch nicht mehr in unterschiedliche Segmente laden, oder ?

Somit kann ich externe Unterprogramme vergessen, oder ?

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #33 am: 22. April 2010, 15:58 »
Richtig, solche Unterprogramme kannst du vergessen.
Das ist mit flachen Binaries nicht möglich. Da du aber einen Bootloader programmierst, der höchstwahrscheinlich keine eigenen Executable-Formate definiert und laden kann, bist du auf flache Binärdateien beschränkt.

Was später geht - und auf 8-Bit-Maschinen verwendet wurde - sind sogenannte Overlays, also du teilst das Programm in mehrere 64K-Blöcke auf (die enthalten meist bisschen gemeinsamen Unterstützungscode) und wenn du eine Funktion aus einem anderen Overlay brauchst, dann "ersetzt" du dein Programm durch das Overlay - wenn die Funktion fertig ist, ersetzt das Overlay sich selbst wieder durch das Hauptprogramm.

Genau diese Technik kannst du weiternutzen, wobei du ja durch den größeren Adressraum netterweise mehrere dieser 64K-Overlays gleichzeitig im Speicher halten kannst. Dazu brauchst du eine Tabelle, die dir angibt, in welchem Overlay sich welche Funktion oder Variable befindet und die steht irgendwo im Dateiformat für Executables. Bei 32-Bit-ELF heißen die Overlays Segmente und die Tabellen stehen ELF-Header. Für PE/LE/a.out gilt entsprechendes.

Dein Bootloader muss aber eine flache Binärdatei sein, was dich aber nicht daran hindert, mehrere Overlays zusammenzulinken. Ohne "Betriebssystem" (Hilfscode) kann dein Bootloader aber nicht damit umgehen. Entweder, du beschränkst dich somit auf 64K oder aber du zerpflückst das Binary im Bootloader in die Bestandteile, schiebst die in verschiede Segmente und machst das zu Fuß.

Kurz: Für den Assembler kommt eine flat binary heraus, den Header und das Zerlegen in die Bestandteile und Overlays Segmente musst du selbst erledigen. Der Assembler hilft dir an der Stelle nicht.

Eventuell guckst du dir mal die Overlay-Technik der 8-Bitter an, der Real Mode des 8086 wurde stark davon inspiriert - auch, um 8080-CP/M-Programme günstig nach 8086 portieren zu können.

Allerdings können weder Minix noch Xenix auf 80286 (vermutl. auch 8086) Programme jenseits 64K Code + 64K Data verarbeiten. Die C-Compiler kamen mit Overlays/Segmentierung grundsätzlich nicht klar und die Technik wurde fallengelassen.

Gruß,
Svenska

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #34 am: 22. April 2010, 16:00 »
Aber wenn ich diese zu einer Binary linken muss, dann kann ich diese auch nicht mehr in unterschiedliche Segmente laden, oder?
Dafür brauchst du ein Dateiformat, dass dein Bootloader natürlich lesen und sich danach richten muss, wie oben beschrieben.

Zitat
Somit kann ich externe Unterprogramme vergessen, oder?
Du müsstest dazu erstmal definieren was du unter "externe Unterprogramme" verstehst, va. wie extern "extern" sein soll. Denn das Keyword "extern" von NASM sagt nur quasi "lieber Assembler, momentan [ = beim Assemblieren] weißt du nicht an welcher Adresse sich das Symbol befindet, aber beim Linken werde ich ganz bestimmt nachreichen wo es ist", d.h. es bezieht sich im Endeffekt direkt aufs Linken und zwar auf das Linken in eine Binary (wenn wir mal shared libraries außen vor lassen), da man die Adresse des Symbols ja "nachreichen" muss. Warum braucht der Assembler (wenn du direkt ins Binärformat assemblieren willst) oder der Linker beim Linken überhaupt die Adresse? Naja, die CPU hat keine Instruktion für call some_awesome_function_name, sondern nur für call <hier kommt die (absolute) Adresse für das Symbol some_awesome_function_name>.

Nun betrachten wir mal den Fall von shared libraries (mit irgendeiner frei gewählten Pseudonotation). Nehmen wir wie oben an, dass du ein Programm schreiben willst, dass call some_awesome_function_name aufrufen möchte und some_awesome_function_name ist in einer shared library (DLL oder was auch immer du dir da vorstellen möchtest, der Punkt ist hier, dass es zwei verschiedene Dateien sind). Ein Assembler (wenn man Binärformat als Ausgabeformat wählt) wird dir dann sagen "oh schade, es gibt aber keine Funktion some_awesome_function_name und ich bräuchte sie jetzt aber dringend, da ich die Adresse sofort eintragen muss", der Linker (wenn man ihm nicht sagt, dass er eine shared library benutzen soll) wird sagen "oh schade, irgendeine Objektdatei wollte some_awesome_function_name aufrufen, aber ich weiß nicht wo ich das finden könnte" und ein Linker dem man beim Linken auch die shared library übergeben hat (d.h. er weiß wo das Symbol später einmal zu finden sein wird) wird sagen "oh toll, irgendwoher krieg ich das Symbol und die Schmutzarbeit in der Callinstruktion die Adresse einzutragen muss dann irgendein Idiot zur Laufzeit machen" (der Idiot ist natürlich hier dann der Bootloader) und wird ungefähr sowas als Datei ausgeben
// Teil des Dateiformats
Benötigte shared libraries:
abc.dll

Relocation Table:
An Adresse 0x1234 muss noch die Adresse des Symbol "some_awesome_function_name" aus abc.dll eingetragen werden

// Der ausgegebene Code (der Maschinencode für call alleine soll hier 4Byte sein
// und direkt danach soll die Adresse an die gesprungen werden soll stehen)
0x1230 call 0
Zur Ladezeit deines Programms/Kernels muss dann irgendjemand (= Du/dein Bootloader) die abc.dll laden, dann die Relocation Table durchgehen und das Symbol "some_awesome_function_name" (Die Datei abc.dll muss dazu natürlich auch ein Dateiformat haben, dass eine Tabelle besitzt die Funktionsnamen auf Adressen abbildet, also hier some_awesome_function_name auf zB 0x6789) in der Datei abc.dll finden und die Adresse des Symbols nach 0x1234 schreiben.

Ich hoffe, dass macht klar, warum man dabei Dateiformate braucht.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #35 am: 22. April 2010, 18:43 »
Hallo,


@bscreator:

ich hab mal in einem FAT12/16/32-Bootsektor einen Loader für eine DOS-EXE untergebracht (für maximal die ersten 512kBytes), das relozieren (in dem Fall nur Segment-Nummern eintragen) hat natürlich nicht mehr rein gepasst. Das könnte man aber im ersten Code in der EXE selber erledigen (passende Parameterübergabe vom Bootsektor in die EXE vorausgesetzt). DOS-EXE-Dateien werden nicht so wie von bluecode (10:36) beschrieben verarbeitet sondern die werden einfach am Stück in den Speicher geladen und dann überarbeitet. Der Vorteil meiner Variante ist das man ein ganz normales Dateisystem verwenden kann (das ist mir persönlich sehr wichtig) und DOS-EXE-Dateien können von einigen älteren Tools erzeugt werden. Wenn man auf das relozieren der EXE verzichtet ist man natürlich an die 64kBytes gebunden aber das ist deutlich genug um darin einen Second-Stage-Bootloader unterzubringen der dann auch selber den PM für den Kernel vorbereitet. Ich hab damals mein eigentliches PM-Programm als Flat-Binary einfach an die EXE drangehangen und es zur Laufzeit mit seiner speziellen Signatur im Speicher gesucht, der DOS-EXE-Stub musste dann nur Speicher vorbereiten und den PM ordentlich aufsetzen.

Als Tool-Chain für den Assembler-Part habe ich den MASM 6 benutzt aber der letzte Borland C-Compiler liefert auch passende OBJ-Dateien welche der MS-Linker problemlos zu normalen DOS-EXE-Dateien verarbeitet.


Eine anderes Problem das ich sehe ist noch das jemand, der Object-Dateien per copy zusammenfummeln will, sich vielleicht erst mal mit der grundsätzlichen Arbeitsweise von Compiler/Assembler/Linker auseinandersetzen sollte. Vielleicht kann da mal jemand ein passendes Tutorial suchen und im Wiki-Anfänger-Artikel verlinken. Ich denke das man, bevor man mit der Entwicklung eines eigenen OS anfängt, mit der Tool-Chain per Du sein sollte.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

bscreator

  • Gast
Gespeichert
« Antwort #36 am: 23. April 2010, 11:42 »
Zitat
also du teilst das Programm in mehrere 64K-Blöcke auf
Damit meinst du, dass ich einfach das Programm in mehrere 64k grosse Dateien zerlege, oder ?
Dann muss ich auch jede einzelne Datei in einen eigenen Sektor der Floppy schreiben, damit ich die Datei(bzw. das "Unter"Programm) in den Speicher laden kann, oder ?
DAS MIT DER 8-bit-TECHNIK WERD ICH MIR AUF JEDEN FALL INS AUGE FASSEN

PS: Wie kann ich nachprüfen, ob mein Programm GENAU 64k gross ist ? Hoffentlich nicht nur so, indem ich mit einem HEX-Editor die Bits zähle...

Zitat
das man ein ganz normales Dateisystem verwenden kann (das ist mir persönlich sehr wichtig
Ich persönlich würde auch gern ein Dateisystem für mein BS schreiben (am besten eines auf FAT12-Basis, damit ich wenigstens mit Windows formatierte Floppys auslesen kann) aber das ist, aus meiner Sicht, sehr kompliziert und es gibt meiner Ansicht nach auch keine Tutorials dafür, die das Erstellen eines Dateisystems, z.B. anhand eines NASM-Beispiels, treffend, kurz und präzise erklären
« Letzte Änderung: 23. April 2010, 11:46 von bscreator »

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #37 am: 23. April 2010, 14:06 »
Die Blöcke müssen nicht unbedingt 64K groß sein.

Es geht darum, dass du beispielsweise ein Programm hast, was zu groß ist und es dann aufspaltest in mehrere kleine Bereiche, zwischen denen du umherschaltest. Die Bereiche liegen ja in verschiedenen Segmenten, also musst du wissen, welche Funktion an welcher Adresse in welchem Segment liegt.

Und genau diese Informationen musst du per Hand in deine Dateien schreiben, solange du kein richtiges Binärformat benutzt. Copy reicht da halt nicht.

Wenn du dein Programm kompilierst und es kommt eine Datei mit exakt 65536 Bytes Dateigröße raus, dann ist dein Programm genau 64 KB groß. ;-)

Ein Sektor auf der Floppy hat übrigens 512 Bytes und ist damit eine Größenordnung kleiner als die Overlaytechnik; wenn es dir also um die nächsten 512 Bytes geht, ist das bisschen übertrieben.

Ein Dateisystem auf FAT12-Basis ... du Scherzkeks, nimm doch direkt FAT12? Da gibt es auch Tutorials für.

Gruß,
Svenska

bscreator

  • Gast
Gespeichert
« Antwort #38 am: 23. April 2010, 15:55 »
Zitat
Es geht darum, dass du beispielsweise ein Programm hast, was zu groß ist und es dann aufspaltest in mehrere kleine Bereiche, zwischen denen du umherschaltest. Die Bereiche liegen ja in verschiedenen Segmenten, also musst du wissen, welche Funktion an welcher Adresse in welchem Segment liegt.
Das ist mir schon alles klar, aber damit ich mein BS von einer Floppy laden kann, muss ich doch erst mein Programm in 512er-Blöcke aufteilen, dann die einzelnen 512Byte-Files auf Sektoren der Floppy verteilen. (Damit ich dann die Sektoren (die Dateien) auch mit dem INT 13 in Bereiche des Speichers, bzw. in verschiedene Segmente, schreiben kann.)

Zitat
Ein Dateisystem auf FAT12-Basis ... du Scherzkeks, nimm doch direkt FAT12? Da gibt es auch Tutorials für.
Schon, aber da hab ich bisher nur welche mit C-Code gefunden. Ich verwend eben Assembler.

Gruss,
bsc

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #39 am: 24. April 2010, 03:14 »
Erstens: Wie du ein Programm intern strukturierst und wie du ein Programm auf dem Datenträger ablegst, sind zwei komplett verschiedene Paar Schuhe. Die Overlay-Technik hat nichts, aber auch garnichts, mit der Ablage auf Platte zu tun.

Was du willst, ist eine Routine, die ganz simpel 128 Sektoren in Folge hintereinander in den Speicher lesen kann, also 64K. Wie du dann weiterarbeitest, spielt keine Rolle. Am einfachsten erzeugst du eine (auf 512 Byte) gepaddete flache Binärdatei und kopierst die mit dd oder rawrite auf die Diskette. Fertig.

Und wenn du C-Code nicht in Assembler umwandeln kannst, wirst du später bei den komplizierteren Themen große Probleme kriegen. Selbst ist der Compiler... ;-)

Gruß,
Svenska

 

Einloggen