Das Anliegen steht ja schon in der Überschrift:
Was könnt Ihr empfehlen, wenn man Anfangen will, das Programmieren in Assemblersprache zu lernen?
Was gibt es, was braucht man, also Bücher, Programme usw...?
Das Anliegen steht ja schon in der Überschrift:
Was könnt Ihr empfehlen, wenn man Anfangen will, das Programmieren in Assemblersprache zu lernen?
Was gibt es, was braucht man, also Bücher, Programme usw...?
Pascal/C und erstmal Inlineassembler versuchen, dann musst du dich schonmal nicht mit Linken, Speichermodellen usw. herumschlagen und in der Hilfe hast du auch ein paar Infos zu Assembler.
Wenn du wirklich ganz banal erstmal den Hintergrund von Assembler verstehen willst:
https://peterhigginson.co.uk/lmc/
Wikipediaeintrag: https://en.wikipedia.org/wiki/Little_man_computer
Grundübungen: Addierer, Subtrahierer, Multiplizierer, Modulo, Dividierer,
In dieser Reihenfolge (von leicht zu schon etwas anspruchsvoller)
Wenn du noch die Funktionale Logik einer CPU und deren Assembly Programmierung verstehen willst, hab ich noch alte Logisim Aufgaben vom Studium.
Computerarchitektur:
Hintergrund Assembly Ladebefehl in ein Register / Speichern aus einem Register
War schon ganz lustig
Mein problem war dann, das auf x86 anzuwenden. Was willst du schon auf dem Bildschirm darstellen, wenn ich noch nicht einmal herausfinden kann, auf welche Adresse ich schreiben muss um was auf dem Bildschirm zu bekommen.
Wenn ich Register lese... ohje.. Erinnerungen werden wach...
ZitatWas willst du schon auf dem Bildschirm darstellen, wenn ich noch nicht einmal herausfinden kann, auf welche Adresse ich schreiben muss um was auf dem Bildschirm zu bekommen.
Ralf Browns Interrupt Liste: http://www.ctyme.com/intr/int.htm
Int 10h
Dann auf Segment A000, für Text tuts ansonsten auch Int 21h
Wenn du wirklich ganz banal erstmal den Hintergrund von Assembler verstehen willst:
Maschinensprache und Logikbausteine sind dann übrigens noch ein - zwei Level unterhalb von Assembler
Aber damit konnte ich erstmal verstehen was da passiert. Wenn ich dann noch wie oben Erklärungen hab wohin was geschrieben ist, wirds noch besser.
Zuhause werf ich mal Einblick auf die Seite.
Besorg Dir "PC Intern 2.0" von Michael Tischer, damit habe ich es vor 30 Jahren gelernt...spannend geschrieben mit vielen Beispielen.
Dieses hier
https://www.amazon.de/Intern-2…cl-Diskette/dp/3890113311
inkl. 5,25" Diskette
Hm, vielleicht muß ich gar nicht so weit ausholen:
Ich will Code in ein BIOS einschleusen, um die Initialisierung des Chipsatzes etwas nachzujustieren. Dazu hab ich in diesem Buch "BIOS DISASSEMBLY NINJUTSU UNCOVERED" von Darmawan Mappatutu Salihun auf Seite 217 folgenden Code gefunden:
; ---------------------- file: mem_optimize.asm -------------------------
use16
start:
pushf
cli
mov cx, 0x50 ; Patch the in-order queue register of
; the chipset
call Read_PCI_Bus0_Byte
or al, 0x80
mov cx, 0x50
call Write_PCI_Bus0_Byte
mov cx, 0x64 ; DRAM Bank 0/1 Interleave = 4 way
call Read_PCI_Bus0_Byte
or al, 2
mov cx, 0x64
call Write_PCI_Bus0_Byte
mov cx, 0x65 ; DRAM Bank 2/3 Interleave = 4 way
call Read_PCI_Bus0_Byte
or al, 2
mov cx, 0x65
call Write_PCI_Bus0_Byte
mov cx, 0x66 ; DRAM Bank 4/5 Interleave = 4 way
call Read_PCI_Bus0_Byte
or al, 2
mov cx, 0x66
call Write_PCI_Bus0_Byte
mov cx, 0x67 ; DRAM Bank 6/7 Interleave = 4 way
call Read_PCI_Bus0_Byte
or al, 2
mov cx, 0x67
call Write_PCI_Bus0_Byte
mov cx, 0x68 ; Allow pages of different banks to be
; active simultaneously
call Read_PCI_Bus0_Byte
or al, 0x44
mov cx, 0x68
call Write_PCI_Bus0_Byte
mov cx, 0x69 ; Fast DRAM precharge for different banks
call Read_PCI_Bus0_Byte
or al, 0x8
mov cx, 0x69
call Write_PCI_Bus0_Byte
mov cx, 0x6C ; Activate Fast TLB lookup
call Read_PCI_Bus0_Byte
or al, 0x8
mov cx, 0x6C
call Write_PCI_Bus0_Byte
popf
clc
retn ; Indicate that this POST routine was successful
; Return near next POST entry
; -- Read_PCI_Byte__ --
; in: cx = dev_func_offset_addr
; out: al = reg_value
Read_PCI_Bus0_Byte:
mov ax, 8000h
shl eax, 10h
mov ax, cx
and al, 0FCh
mov dx, 0CF8h
out dx, eax
mov dl, 0FCh
mov al, cl
and al, 3
add dl, al
in al, dx
retn
; -- Write_Bus0_Byte --
; in: cx = dev_func_offset addr
; al = reg_value to write
Write_PCI_Bus0_Byte:
xchg ax, cx
shl ecx, 10h
xchg ax, cx
mov ax, 8000h
shl eax, 10h
mov ax, cx
and al, 0FCh
mov dx, 0CF8h
out dx, eax
add dl, 4
or dl, cl
mov eax, ecx
shr eax, 10h
out dx, al
retn
; --------------------- file: mem_optimize.asm --------------------------
Alles anzeigen
den ich teilweise verstehe und in einigen Teilen nicht:
Es geht bei diesem Beispiel darum, dem Speichercontroller des VIA Apollo Pro 133 (Slot 1, Pentium II) etwas auf die Sprünge zu helfen. Dazu werden einige Werte in den Registern der Northbridge VT82C693A nach der Initialisierung durch das BIOS geändert. Im oberen Teil wird acht mal ein bestimmtes Register des Chipsatzes festgelegt, dessen Wert geändert und zurückgeschrieben.
Wo meine Probleme beginnen, sind die Funktionen "READ_PCI_Bus0_Byte" und "WRITE_PCI_Bus0_Byte"
Zeilen 70, 71 und 72: Hier wird die Adresse des zu lesenden PCI-Geräts und dessen Register gebaut. Benötigt wird laut dem Buch S. 21/22 jetzt am Beispiel der letzten Optimierung (Zeilen 53-57) die Adresse 8000 006Ch.
- 70: Erst wird der Wert 8000h ins AX-Register geschrieben
- 71: Dann wird er um 16 Stellen nach links geschoben. Ich nehme mal an, daß in EAX jetzt 8000 0000h stehen soll, also binär betrachtet 16 Nullen angehängt wurden. Warum wird der Wert nicht gleich so reingeschrieben?
- 72: Das Register-Offset 0x6C aus dem oberen Teil wird nach AX geschreiben, so daß in EAX jetzt 8000 006Ch stehen müßte.
Mit Zeile 73
kann ich gar nichts anfangen. Der Sinn und Zweck erschließt sich mir nicht.
Zeile 74 öffnet den Adressport 0xCF8h zum Zugriff auf das PCI-Gerät
Zeile 75 sendet die erstellte PCI-Adresse in den eben geöffneten Port im I/O-Adressraum der CPU
Zeile 76 öffnet den Datenport des PCI-Buses, aber müßte da nicht statt 0FCh eigentlich 0CFCh stehen?
Die Zeilen 77, 78 und 79 sagen mir wieder gar nichts
In Zeile 80 wird vermutlich der Wert des PCI-Registers nach AL geschrieben, um dann nach den Vorgaben aus Zeile 55 modifiziert zu werden.
Kann mir bitte jemand die unklaren Stellen erklären?
Mit der WRITE-Funktion will ich mich erst beschäftigen, wenn ich die READ-Funktion verstanden habe. Vielleicht haben sich ja dann auch schon einige Unklarheiten erledigt.
So, da es hier anfängt zu gewittern und ich vor lauter Müdigkeit nur noch Rechtschreibfehler produziere und zeitraubend korrigiere, höre ich mal auf und warte auf Eure hilfreichen Antworten. hilft alles nicht
Eine Nacht drüber geschlafen, heute morgen nochmal ins Buch geschaut und auf dem Weg zum Einkaufen ist der Groschen dann gefallen:
Beim Zugriff auf den PCI-Bus müssen die letzten beiden Stellen der Adresse den Wert 0 haben. Warum auch immer, läßt sich so halbwegs aus den Angaben auf S. 14f ableiten.
Zeile 73 erledigt das und nullt die Bits 1-0.
Mehr nach dem Essen...
Die Unklarheit in Zeile 76 hat sich auch erledigt: in dx steht ja schon 0CF8h aus Zeile 74. Durch überschreiben der letzten acht Bits mit dem Wert 0FCh wird daraus die Datenportadresse 0CFCh des PCI-Bus.
In Zeile 77 wird das in Zeile 73 genullte Ende der Offsetaddresse in eax mit dem Wert aus dem cx-Register wiederhergestellt.
Zeile 78 nullt nun die Bits 7-2 der Offsetadresse in ax, genauer in al. Warum, weiß ich aber noch nicht, DER Groschen hängt noch in der Luft .
Zeile 79 addiert nun die letzten beiden Stellen der Offsetadresse an den PCI-Datenport. Das ist wohl deshalb notwendig, weil durch das Nullen der letzten beiden Bits der Adresse in Zeile 73 jeweils 4 Offsets immer die gleiche PCI-Adresse liefern.
Aber warum man da nicht auch das Kommando or nehmen kann, ist mir auch noch schleierhaft .
Soweit meine laienhafte Erklärung der READ-Funktion.
Ich will Code in ein BIOS einschleusen, um die Initialisierung des Chipsatzes etwas nachzujustieren. Dazu hab ich in diesem Buch "BIOS DISASSEMBLY NINJUTSU UNCOVERED" von Darmawan Mappatutu Salihun auf Seite 217 folgenden Code gefunden:
So, ich nehm jetzt mal meinen alten Thread und funktioniere ihn ein bißchen um:
Es geht immer noch darum, Code in ein BIOS nach dieser Methode einzuschleusen. Die Patch-Dateien dafür habe ich nach dem obigen Schema von Darmawan Mappatutu Salihun a.k.a. Pinczakko schon etwas länger fertig. (Warum steht da eigentlich "Brainfuck-Quellcode"? Kann man das auch irgendwie normal ausdrücken? Das ist Assembler.)
Die Probleme sind nun
- das Auffinden der POST Jump Table im BIOS,
- die Identifizierung einer nicht genutzten Prozedur dort und
- das Umleiten der Sprunganweisung zu dieser Prozedur hin zum Patch.
Nachdem ich vor einem halben Jahr beim Dekompilieren des BIOS kaum Fortschritte gemacht habe, hab ich den Mist erst mal zur Seite gelegt
Die unterschiedlichen Adressen des Codes in der BIOS-Datei bzw. der original.tmp im Vergleich wie es dann im RAM vorliegt, haben mich einfach wahnsinnig gemacht
Die letzten Tage habe ich dann noch mal angefangen, die Artikel von Pinczakko zu lesen, und darin den Startpunkt in der original.tmp gefunden. Also diese direkt noch mal durch IDA Free gejagt, den Startpunkt gesucht und den Jumpanweisungen gefolgt. Dabei begegnete mir doch glatt Code, der dem unter den Punkten 7.2.1, 7.2.2 und 7.2.3 (nur die ersten beiden Schnipsel) sehr ähnlich sieht. Allerdings hab ich den Code zwischen den Sprunganweisungen nicht im geringsten verstanden und habe das Gefühl, daß in dem älteren BIOS irgendwas anders läuft, da die POST Jump Table etwas komisch aussah.
Daher wollte ich Euch jetzt mal Teile des Codes zeigen und ein paar Fragen dazu stellen. Ich hoffe, Ihr habt alle breite Bildschirme . Die ersten 4 Spalten sind meine Deutung dessen, was da passieren soll, der Code mit Adresse, wie er in der Datei vorliegt, ist in den letzten beiden Spalten:
Eintrittspunkt vom Bootblock, Sprung auf die nächste Adresse | Register | Wert binär | Wert hex | seg000:1F80D jmp near ptr unk_EE12 |
|
Schreibe 0 nach ax | ax | 0000 0000 0000 0000 | 0h | seg000:1EE12 mov ax, 0 |
|
Schreibe ax nach ss (Stapelsegment, stack segment) | ss | 0000 0000 0000 0000 | 0h | seg000:1EE15 mov ss, ax |
|
Schreibe 1000h nach sp (Stapelzeiger, stack pointer) | sp | 1 0000 0000 0000 | 1000h | seg000:1EE17 mov sp, 1000h |
|
seg000:1EE1A call near ptr unk_EDFC |
|||||
Hole vom Prozessorstapel ss (?) nach bx | bx | 0000 0000 0000 0000 | 0h | seg000:1EDFC pop bx |
|
Subtrahiere 200h von sp | sp | 1110 0000 0000 | E00h | seg000:1EDFD sub sp, 200h |
|
Schreibe Stapelzeiger in den Basiszeiger (base pointer) | bp | 1110 0000 0000 | E00h | seg000:1EE01 mov bp, sp |
|
Schiebe ds auf den Prozessorstapel (Wert von ds unbekannt, müßte noch vom Bootblock sein) | ss | ??????? | seg000:1EE03 push ds |
||
Schiebe ax auf den Prozessorstapel | ss | 0000 0000 0000 0000 | 0h | seg000:1EE04 push ax |
|
Schiebe 40h nach ax | ax | 100 0000 | 40h | seg000:1EE05 mov ax, 40h ; '@' |
|
Schiebe ax ins Datensegment (data segment) | ds | 100 0000 | 40h | seg000:1EE08 mov ds, ax |
|
??? | seg000:1EE0A assume ds:nothing |
||||
Schreibe bp nach ??? | ??????? | seg000:1EE0A mov ds:0A1h, bp |
|||
Hole vom Prozessorstapel nach ax | ax | 0000 0000 0000 0000 | 0h | seg000:1EE0E pop ax |
|
Hole vom Prozessorstapel nach ds | ds | ??????? | seg000:1EE0F pop ds |
||
??? | seg000:1EE10 assume ds:nothing |
||||
Schiebe bx auf den Prozessorstapel | ss | 0000 0000 0000 0000 | seg000:1EE10 push bx |
||
seg000:1EE11 retn |
|||||
seg000:1EE1D call sub_4A9C |
Fragen:
1. Holen bzw. schieben pop und push auf das Register ss? Wenn nein, auf welches?
2. Was bedeutet assume ds:nothing in den Zeilen 13 und 17, wo doch ds gerade in der Zeile darüber einen Wert bekommen hat? Oder weiß IDA nach der Codeanalyse einfach nicht, welcher Wert da sein soll? Die Adresse von assume stimmt ja seltsamerweise auch mit der des nachfolgenden Befehls überein Im Originalcode ist das auch andersfarbig markiert.
3. Was tut der rot markierte Befehl mov ds:0A1h, bp? In bp steht nach meiner Deutung E00h, in bp 40h.
4. Was tut diese ganze Unterfunktion unk_EDFC in der letzten Spalte?
Freue mich schon auf Antworten
Ich kann Dir keine definitive Hilfe leisten(da ich sowas noch nie gemacht habe) aber...
die interrupts mittels "cli" "abzuschalten" ohne sie mit "sti" wiederherzustellen scheint seltsam - vielleicht passiert das aber in einem anderen Teil des codes.
Das "ds:xxxx" ist ein segment override mit einer absoluten adresse xxxx. Ich nehme an der code ist "tiny" wo alle segmente auf die selbe Adresse zeigen.
push / pop bezieht sich immer indirekt auf ss was jedoch im kleinen Speichermodell nicht von Bedeutung ist, denn cs = ds = ss(64KiB Speicherraum).
"assume seg:nothing" erklärt den vorher erklärten Werte für das segment Register als ungültig. Es sollte also ein Fehler bei der nächste Indirektion einer Adresse auf Daten geschehen. Nachdem hier aber noch eine Indirektion erfolgt, ist es vielleicht ein "Trick" den ich nicht kenne oder ein Fehler seitens IDA bei der "Übersetzung".
Zeile 79 - "and" und "or" liefern das gleiche Ergebnis wenn die unteren bits eines der Operanden 0 sind - ist also Formsache.
Bitte alles Gesagte mit Vorsicht geniessen.... wenn man nicht jeden Tag aktiv das Ganze betreibt, wird man schnell rostig.
Danke für die Erklärung, auch wenn ich jetzt am Morgen noch wenig davon verstehe. Darüber muß ich noch ne Weile nachdenken
Hab gestern Abend noch die POST Jump Table gefunden, glaube ich jedenfalls. Sie liegt schon am letzten Sprungziel. Sie sah nur so komisch aus, weil IDA den BIOS Code nicht versteht und ich sowohl IDA als auch den BIOS Code nicht verstehe . Hab einfach mal den Zufall zu Hilfe genommen und mit Maus und ein paar Tasten wild hin und her geklickt und gedrückt. Plötzlich formte sich das etwas, das genauso aussah wie das, was Herr Pinczakko da auf seiner Webseite als E0_POST_TESTS_TABLE stehen hat.
Ich schreib noch etwas, vielleicht bringt Dich das ein Stückchen weiter - aber kann auch sein das ich an Deinen Fragezeichen vorbeierzähle, da es nicht direkt mit Deinem Problem zusammenhängt. Hole auch soviele weiter Meinungen(z.B. bei stackoverflow oder das TASM / MASM / NASM manual) wie möglich ein um Dich vor unabsichtlichen Fehlern zu schützen.
Segment / "assume"
Bezüglich der segmente - die Direktiven im assembler wie z.B. "assume" klären das die Segmente gültig sind, sprich code, daten, stack sind korrekt initialisiert und das Programm findet somit gültige Bedingungen für eine hoffentlich korrekte Ausführung vor. Wenn Dein assembler listing nicht an ein anderes Objekt, welches das Hauptprogramm stellt, andockt, dann musst Du das im assembler mittels Direktive, wie z.B. assume, regeln.
Segment Override
Der segment-override wurde früher oft benutzt wenn jemand, ein einem Speichermodell, wo nur ein Datensegment voranden ist(z.B. tiny / small), in ein anderes(z.B. dem VGA Speicher) schreiben wollte. Da die "lineare", eingeblendete, Adresse des VGA(0xA0000) grösser als 16 bit ist, passt sie nicht in ein Standardregister wie ax, bx etc. sondern ergibt erst im Tandem mit einem Segment die Möglichkeit dort zu lesen / schreiben. Das war der grosse Trick des PCs die magischen 64KiB im "real mode" zu umgehen - Segment:Offset Adressen.
Es wurde also ein linearer 1MiB grosser Addressraum mittels eines Hilfskonstrukt aus zwei 16 bit Registern etwas "umständlich" zugänglich gemacht.
Das Segmentregister "es" wurde hier z.B. mit dem Wert A000(Segmenteil der linearen Adresse A0000(-> A0000) des VGA Bereichs) geladen und dann mittels
"mov byte ptr es:[di], byte_value"
z.B. ein Pixel gesetzt. Denn die effektive Adresse ist hier "es * 16 + di". Nun können die hinteren 16 bit der Adresse(A0000) mittels "di" ohne Probleme angesprochen werden und man "wandert" somit über den Schirm.
Zum Lernen
Vielleicht wäre es einfacher wenn Du die ganz alten, oder systemnahen, DOS "Hindernisparcours" vorerst wegglässt, und einfach Assembler(hilfsroutinen) im 32bit protected mode benutzt, wobei Du hier an einen geeigneten Compiler "andockst".
So ein Compiler, wie z.B. WatcomC, hat bereits alles korrekt aufgesetzt sodas Du auf einen 64+MiB grossen, linearen Addressraum ohne Segmentierung (dank DPMI) zugreifen kannst. Einziger Nachteil ist, dass eine Interaktion mit dem System(z.B. BIOS / SVGA VBE1.2, etc.) welches realen Dosspeicher braucht, ein wenig aufwendiger ist.
Nachdem Du hier Erfahrung gesammelt hast, gehst Du wieder zurück zum 16bit mode und erledigst Probleme die eine umständlichere Herangehensweise erfordern.
Du darfst die Programmierung selbst nicht mit den Eigenheiten bezüglich der Ansprache von Geräten verwechseln. Komplexitäten ergeben sich oft durch das Prozedere etwas "fachgerecht" zu erledigen und nicht durch die formale Sprache mittels Du der dies erledigen willst. ModeX z.B. ist, meiner Meinung nach, umständlich da die hardware die diesen bereithält relativ komplex ist. Die vom user benutzte Sprache ist hier eher unschuldig.
Das mit dem bios ist extrem interessant, aber zum Lernen eher schlecht da Du von Details die jenseits von assembler liegen abgelenkt wirst - Syntax- und hardware-probleme verschmelzen dann zu einem tödlichen Brei. Zudem ist das 16bit Programmiermodel relativ komplex durch z.B. Speicher-Segmentierung und Einschränkung(en) beim Registergebrauch.
Wichtig wäre eher mal "x86", "real mode", "segment", "interrupts - software / hardware" zu recherchieren.
Da hast Du wohl recht. Alleine die Art wie der PCI-Bus adressiert wird, immer mit einer Doppelnull am Adressende und den Offset dann hinterher rüberschieben, ist wohl so ein Detail, das einen fürchterlich ablenkt. Und so ein BIOS ist wirklich sehr komplex , was einfacheres ist für den Anfang besser geeignet.
Das BIOS zu hacken war halt mein ursprünglicher Antrieb dafür, mich mit diesen Assemblerbefehlen zu befassen. Inzwischen bin ich mir sehr sicher, daß ich die Sprungtabelle für die Selbsttests gefunden habe. Ebenso die ungenutzten Prozeduren da drinnen. Damit sind von diesen Problemen
- das Auffinden der POST Jump Table im BIOS,
- die Identifizierung einer nicht genutzten Prozedur dort und
- das Umleiten der Sprunganweisung zu dieser Prozedur hin zum Patch.
Nr. 1 und Nr. 2 gelöst und ich muß nur noch die alte Sprungadresse gegen die neue austauschen
Wer stellt sein Board als Testobjekt für das gehackte BIOS zur Verfügung? Ich will meins nichts schrotten, falls es schief geht
Vielleicht schaff ich das auch mit fast ganz ohne Assemblerkenntnissen
Du hast eh einiges geleistet - wahrscheinlich bist Du in ein paar Stunden oder Tagen damit fertig. Du kannst auf jeden Fall Stolz auf Deinen Forscherdrang sein!
Solltest Du wirklich etwas vertieft Programmieren wollen, dann solltest Du trotzdem einen anderen Ansatz wählen, da Du sonst total verwirrt wirst... und dann alles hinwirfst.
Gutes Wissen ist rar und es sich anzueigenen schwierig - selbst in Zeiten des "internets".
Vielen Dank!
Adressen sind ausgetauscht. Jetzt hab ich tierisch Schiß davor, das zu flashen . Zum Glück ist der Rechner nur halb zusammengebaut und noch ohne Netzteil.
Lies dir zur Sicherheit erst mein Rumgestochere im Flash-ROM durch
Restauration: Highscreen InduS-Tower mit Intel Advanced/ZP + P90
Dein Rechner hat mit Sicherheit auch einen Recovery-Modus. Lerne ihn vorher zu benutzen
Besorg Dir "PC Intern 2.0" von Michael Tischer, damit habe ich es vor 30 Jahren gelernt...spannend geschrieben mit vielen Beispielen.
Warum gerade Ausgabe 2.0? Ausgabe 3.0 ist immerhin auf der Höhe von DOS 5 und Ausgabe 4 ist auch noch PräWindows95 Habe auch schon mit dem Gedanken gespielt und war mir unschlüssig.
Genau die selbe Frage habe ich mir auch gestellt. 3.0 ist wenigstens verfügbar. Bei archive.org gibts die englische Fassung von, ja wovon eigentlich? Schätze v1 oder v2.
Lies dir zur Sicherheit erst mein Rumgestochere im Flash-ROM durch
Restauration: Highscreen InduS-Tower mit Intel Advanced/ZP + P90
Dein Rechner hat mit Sicherheit auch einen Recovery-Modus. Lerne ihn vorher zu benutzen
Hätte ich das nur vorher gelesen, hätte es auch nichts genutzt: Der Rechner hat keinen Recoverymodus. Dazu ist er zu alt.
Aber mir ist heute bei der Diskussion über die Suchfunktion aufgefallen, daß ich Euch noch gar nicht erzählt habe, worum es hier eigentlich genau geht. Und das, wo ich vor einem halben Jahr schon in 3 4 anderen Foren um Rat gefragt habe. Ich stelle Euch das mal vor, wenn alles funktionieren sollte.
Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!