Hallo Besucher, der Thread wurde 10k mal aufgerufen und enthält 40 Antworten

letzter Beitrag von -trb- am

Adressfragen bezüglich POKE bzw PEEK

  • von hier: http://mclauchlan.site.net.au/…king/C-Hacking12/gfx.html

  • Da ich in Assemlber nicht so bewandert bin und auch dieses Setzen von Bit y in Register x bis heute noch nicht kapiert habe, würde ich mich freuen, wenn mir jemand den POKE dazu posten könnte. Beispiel: poke65299,peek(65299)andxory or poke65299,x


    Oder; jemand versucht es mir zu erklären, was aber vergebene Liebesmüh ist. Ich hab diverse Bücher zu diesem Thema durchgelesen und kapier es immer noch nicht, sorry. Ich brauch halt ne Hochsprache zum Programmieren.

  • poke 65287,peek(65287) or 128 bzw. poke 65287,136


    Rückgängig wäre: poke 65287,peek(65287) and 127 bzw. einfach poke 65287,8



    Noch ein kurzer Erklärungsversuch:


    Mit OR werden die Bits halt gesetzt (hier: 128=2^7, also Bit7); bei AND die fehlenden Bits gelöscht (bei 127 fehlen 128=2^7=Bit7 zu 255), aber die bestehenden Bits bleiben. Im obigen Falle würde auch AND 8 funktionieren, es würden aber ggf. gesetzte Bits für 40/38 oder Multicolor gelöscht.

  • In diesem Zusammenhang ist mir ohnehin schleierhaft, warum von vielen da der Aufwand betrieben wird, einzelne Bits in den Videochip-Registern zu setzen/löschen, während andere Bits in Ruhe gelassen werden sollen. Im Regelfall ist sehr genau bekannt, was in allen 8 Bits des betroffenen Registers zu stehen hat, und dann stellt man den richtigen Wert anhand der Bitbelegung zusammen und schreibt ihn rein. Niemand ist damit geholfen, wenn z.B. im angegebenen Beispiel der Multicolor-Modus aktiv bleibt (z.B. weil ein böswilliger User den vorher aktiviert hat), obwohl das eigene Programm das vielleicht gar nicht will!


    Bei der Programmierung von I/O sieht das anders aus, gerade wenn Bits auch "von außen" verändert werden können. Dann ist sorgfältiges Ausmaskieren auf jeden Fall angezeigt. Ähnliches gilt auch für die Interrupt-Register der Videochips.

    Zitat von RKSoft

    Oder; jemand versucht es mir zu erklären, was aber vergebene Liebesmüh ist. Ich hab diverse Bücher zu diesem Thema durchgelesen und kapier es immer noch nicht, sorry. Ich brauch halt ne Hochsprache zum Programmieren.

    Sorry, aber das Binärsystem und die Funktion von logischen Verknüpfungen sind Programmiergrundkenntnisse. Egal ob Du in Hochsprachen programmierst oder in einer maschinennahen Sprache. Dazu braucht's auch keine Unmengen an Büchern zu wälzen um das zu verstehen, das dazu relevante Faktenwissen paßt auf eine halbe A4-Seite.


    Aus dem nachfolgend zitierten Beitrag ergab sich damals bereits die Problemlösung:

    Zitat von Mike

    POKEV+7,8 löscht unter anderem Bit 7 des Registers, so daß ein Zeichensatz nach wie vor nur 1K groß ist - also nur die ersten 128 Zeichen definiert werden brauchen, TED invertiert die dann automatisch. Mit Bit 7 = 1 können alle 256 Zeichen frei definiert werden. Der Cursor funktioniert übrigens unabhängig davon!

    Also eben POKEV+7,136 - wie Hexworx oben schon schrieb. Das im anderen Thread mitgelieferte Beispiel reserviert allerdings nur Speicherplatz für den 1K großen Zeichensatz.

  • @Hexworx
    hab das nochmal durchprobiert. Funktioniert nur, wenn man nicht vorher den Multicolor eingeschaltet hat. Ich hab folgendes ausprobiert und mir als nützliche Tipps gespeichert:

    Code
    1. poke65287,0:rem ...Auto-Invers an, Multicolor aus, Rahmen breiter
    2. poke65287,8:rem ...Auto-Invers an, Multicolor aus, Rahmen normal
    3. poke65287,16:rem ...Auto-Invers an, Multicolor an, Rahmen breiter
    4. poke65287,24:rem ...Auto-Invers an, Multicolor an, Rahmen normal
    5. poke65287,128:rem ...Auto-Invers aus, Multicolor aus, Rahmen breiter
    6. poke65287,136:rem ...Auto-Invers aus, Multicolor aus, Rahmen normal
    7. poke65287,144:rem ...Auto-Invers aus, Multicolor ein, Rahmen breiter
    8. poke65287,152:rem ...Auto-Invers aus, Multicolor ein, Rahmen normal

    Sprich, die normalen Werte plus 128 ergeben, daß das automatische Invertieren deaktiviert wird.


    Sorry, aber das Binärsystem und die Funktion von logischen Verknüpfungen sind Programmiergrundkenntnisse. Egal ob Du in Hochsprachen programmierst oder in einer maschinennahen Sprache. Dazu braucht's auch keine Unmengen an Büchern zu wälzen um das zu verstehen, das dazu relevante Faktenwissen paßt auf eine halbe A4-Seite.

    Nichts für ungut, aber ich habe mit dem Programmieren im zarten Alter von 9 Jahre angefangen. Zum Ende der 90er bin ich, zwischen durch mal Turbo Pascal, auf DIV (C ähnliche Sprache), anschließend auf Blitz Basic, Pawn, JavaScript und PHP umgestiegen. Soll heißen, daß ich vor 30 Jahren damit angefangen habe und es bisher nie so benötigte. Das Binärsystem mit den Stellen (8 Bit Bereich) 1,2,4,8,16,32,64,128, welche man mit 0 oder 1 füllen kann, kenn ich. AND und OR sind mir ebenfalls ein Begriff, nur habe ich mich noch nie so ausgiebig damit auseinander gesetzt und mußte es auch nie. Die Sprachen, mit denen ich bisher in meinem Leben zutun hatten, brauchten dies auch nicht so.

  • Auf die Gefahr, hier OT zu werden, hake ich trotzdem mal nach:

    Nichts für ungut, aber ich habe mit dem Programmieren im zarten Alter von 9 Jahre angefangen. Zum Ende der 90er bin ich, zwischen durch mal Turbo Pascal, auf DIV (C ähnliche Sprache), anschließend auf Blitz Basic, Pawn, JavaScript und PHP umgestiegen. Soll heißen, daß ich vor 30 Jahren damit angefangen habe und es bisher nie so benötigte. Das Binärsystem mit den Stellen (8 Bit Bereich) 1,2,4,8,16,32,64,128, welche man mit 0 oder 1 füllen kann, kenn ich. AND und OR sind mir ebenfalls ein Begriff, nur habe ich mich noch nie so ausgiebig damit auseinander gesetzt und mußte es auch nie. Die Sprachen, mit denen ich bisher in meinem Leben zutun hatten, brauchten dies auch nicht so.

    Mich überrascht so eine Aussage von Dir, weil ich sehe, wieviele Games Du in kurzer Zeit aus dem Boden stampfst wie z.B. Frutty Man für den Plus/4, C128 usw., also gute Programmierkenntnisse und eben logisches Denken hast.
    Das Manipulieren von Bits hat ja nichts mit Assembler zu tun, sondern mit Boolsche Algebra.
    Auch auf dem PC in C oder Basic und andere Hochsprachen musst Du doch auch Gedanken über Bits und Bytes machen, z.B. die Wertegrenzen von smallint, int, bigint etc. Das ist ja nicht "Zufall" wieso ein 16Bit INT positive Werte bis 32767 aufnehmen kann und wenn man über diesen Wert geht, kippt die Zahl ins Negative.
    Die logischen Operationen AND, OR, NOT sind gerade auch im BASIC Bereich, auch bis heute in Visual Basic, nach wie vor nötig, wenn man IF....THEN Konstrukte mit kombinierten Bedingungen braucht:


    IF myWert=1 AND myString="" THEN ... END IF
    IF myWert=1 OR myString>"" THEN ... END IF
    etc.


    Was genau macht Dir denn bei den Boolschen Operationen mit Speicherstellen Mühe?



    Ich versuche es mal mit einem Beispiel, auf die Gefahr hin, mich lächerlich zu machen:


    Ein fiktives Beispiel für Boolsche Operationen mit einer Speicherstelle und Bit Manipulation


    Speicherstelle $FF07 (dec 65287) : PEEK(65287) liefert dezimal 182 zurück. In binärer Darstellung: 10110110
    Wenn das höchste Bit 7 (ganz links) geändert werden muss, ohne die anderen Bits anzufassen, benötigen wir einen Befehl, der

    • die gewünschte Speicherstelle ändert
    • das gewünschte Bit entgegennimmt, welches wir ändern wollen
    • den binären Zustandswert 0 oder 1 dieses Bits definiert

    Also in BASIC sowas wie SETBIT(65287,7,0) um das höchste Bit 7 auf den Wert 0 zu setzen (0=löschen) oder SETBIT(65287,7,1) für den Wert 1 (1=setzen).
    Mir wäre nicht bekannt, ob es in den besseren BASIC Varianten sowas gibt. In BASIC V2 sicher nicht.
    Also müssen wir mit einem Workaround arbeiten.


    Wir wissen dass mit POKE<Adresse>, <Wert> der Wert einer Speicherstelle gesetzt wird und mit PEEK(<Adresse>) gelesen wird.
    Auch haben wir in BASIC V2 und höher die Boolsche Operationen AND, OR und NOT.
    Ich gehe davon aus, dass Du diese Boolsche Logik im Grundsatz verstehst. Im C64-Wiki sind diese mit Beispielen erklärt, aber auch in jedem Mathematik/Algebra Buch sollten sie aufgeführt sein.


    Also müssen wir nun mit diesen Befehlen leben und daraus den SETBIT Befehl nachbauen:
    In der Speicherstelle $FF07 (65287) soll nur das Bit 7 gelöscht werden, unabhängig davon, was in der Speicherstelle aktuell steht. Wir wissen aktuell evt. nicht mal ob Bit 7 gesetzt oder gelöscht ist. Wir wollen aber auch die anderen Bits 0-6 nicht antasten.



    PEEK(65287) : liefert und den aktuellen Wert (die Bits) dieser Speicherstelle, also POKEn wir diesen gleich nach dem Auslesen zurück, mit dem Unterschied, dass Bit 7 mit dem Wert 0 gesetzt werden soll.


    Das Bit 7 hat ja einen Dezimalwert von 2^7 = 128. Wir könnten ja auch einfach 128 von der Speicherstelle subtrahieren:
    POKE 65287, PEEK(65287) - 128 ---> ist halt doof wenn Bit 7 nicht gesetzt ist, der Wert der Speicherstelle also < 128 ist, dann gibt's einen Fehler (in BASIC V2: ?ILLEGAL QUANTITY ERROR)


    besser: IF PEEK(65287) > 127 THEN POKE 65287, PEEK(65287) - 128 ---> damit haben wir Bit 7 gelöscht, falls es gesetzt ist. Ist es nicht gesetzt, trifft die IF Bedingung nicht zu und alles ist trotzdem so wie wir es haben wollen.



    Um das Bit 7 zu setzen, können wir einfach 128 zu der Speicherstelle addieren, falls das nicht schon gesetzt ist (also der Speicherstellen-Wert bereits 128 oder höher ist):
    IF PEEK(65287) < 128 THEN POKE 65287, PEEK(65287) + 128 ---> damit haben wir Bit 7 gesetzt, falls es gelöscht ist. Ist es gesetzt, trifft die IF Bedingung nicht zu und alles ist trotzdem so wie wir es haben wollen.


    Damit kannst Du jedes Bit 0...7 mit dessen dezimalen Wertigkeit (1, 2, 4, 8, 16, 32, 64, 128) einfach und geziehlt setzen oder löschen.


    Will man jetzt mehrere Bits so setzen/löschen, wird es komplizierter mit dieser Subtrahieren/Additions-Methode.
    Wir können es uns aber einfach machen und halt eine BASIC Zeile pro Bit verwenden, also nacheinander die Bits manipulieren.


    Nun ist der BASIC Programmierer nicht gerade mit Geschwindigkeit gesegnet und will das Ganze kürzer schreiben und schneller laufen lassen.
    Mit der Boolschen Logik kann man die Bits gezielter manipulieren und man benötigt diese IF Abfrage (=ein Performancekiller) nicht.


    Wahrheitstabelle OR : Wir wissen, dass mit OR zwei Zustandswerte verglichen werden können und wenn einer oder beide davon gesetzt sind, bekommen wir 1 (TRUE) zurück:
    0 OR 0 = 0
    0 OR 1 = 1
    1 OR 0 = 1
    1 OR 1 = 1


    Wahrheitstabelle AND : Es müssen beide Zustandswerte 1 sein, damit wir ein 1 (TRUE) zurück bekommen:
    0 AND 0 = 0
    0 AND 1 = 0
    1 AND 0 = 0
    1 AND 1 = 1


    Das können wir uns zur Bitmanulation zunutze machen.
    Speicherstelle $FF07 (dec 65287) liefert aktuell dezimal 182 zurück. In binärer Darstellung: 10110110
    Wir wollen das Bit 7 löschen, also auf 0 setzen. Wir wissen, egal was Bit 7 aktuell für einen Wert hat, also 0 oder 1, wenn wir diesen mit AND 0 vergleichen, wird eine 0 herauskommen.


    Wir wissen aber auch, dass die Bits 0...6 unangetastet bleiben müssen. Sind sie 0, sollen sie 0 bleiben und sind sie 1, sollen sie 1 bleiben. Aus unserer AND Wahrheitstabelle wissen wir: 0 AND 1 = 0 bzw. 1 AND 1 = 1.
    Unser AND Wert muss also die Bits 0...6 auf 1 gesetzt haben, damit sie bleiben wie sie sind und nur Bit 7 des AND Wertes muss 0 sein, um das Bit 7 der Speicherstelle $FF07 zu löschen.
    Damit ergibt sich der AND Wert 01111111 was dezimal 127 ergibt. Dies wird als "Maskierungswert" bezeichnet, wir "maskieren" die Bits, die wir beeinflussen wollen eben mit 0 oder 1, je nachdem ob wir sie löschen oder setzen möchten (Disclaimer: zumindest habe ich das immer so verstanden)


    Unser POKE mit diesem Maskierungswert ist dann:
    POKE 65287, PEEK(65287) AND 127 ---> damit haben wir Bit 7 gelöscht, egal ob es vorher gesetzt oder nicht gesetzt war. Bit 0...6 bleiben identisch


    Nun wollen wir Bit 7 wieder setzen. Auch hier wieder ohne die Bits 0...6 anzufassen. Aus unserer OR Wahrheitstabelle wissen wir: <aktuellerZustand> OR 0 = <aktuellerZustand> bzw. <aktuellerZustand> OR 1 = 1.
    Da wir die Bits 0...6 unserer Speicherstelle im <aktuellenZustand> behalten wollen, nehmen wir OR 0 für die jeweiligen Bits 0...6 des OR Maskierungswerts, und 1 für Bit 7.
    Also ergibt sich hier der binäre Maskierungswert: 1000000 was dezimal 128 ergibt, weil wir nur Bit 7 setzen möchten. Die Bits 0...6 der Speicherstelle bleiben erhalten, wenn wir diese mit OR 0 vergleichen.


    POKE 65287, PEEK(65287) OR 128 ---> damit haben wir Bit 7 gesetzt, egal ob es vorher gesetzt oder nicht gesetzt war. Bit 0...6 bleiben identisch


    Daraus sehen wir die Vorteile der Boolschen Operation mit AND und OR, um gezielt eines oder mehrere in einem Atemzug (=Anweisung) zu setzen:
    Man nimmt die Bits der Speicherstelle, die man manipulieren möchte, entscheidet setzen (mit OR) oder löschen (mit AND) und definiert sich dann den binären Maskierungswert, welchen man in der Anweisung mit OR/AND in dezimal für den PEEK-Wert verknüpft.


    Ich hoffe, dieser langer Text, hat etwas dazu beigetragen, die Bitmanipulation zu verstehen.

  • Damit ergibt sich der AND Wert 01111111 was dezimal 127 ergibt. Dies wird als "Maskierungswert" bezeichnet, wir "maskieren" die Bits, die wir beeinflussen wollen eben mit 0 oder 1, je nachdem ob wir sie löschen oder setzen möchten

    setzen -> unverändert lassen


    "Rahmen breiter/normal" ist vertauscht.


    Am liebsten mag ich ja solche Tabellen:


    Bit 7 6 5 4 3 2 1 0
    Wertig-
    keit
    128 64 32 16 8 4 2 1
    Invers
    off
    0=on
    NTSC
    0=PAL
    TED
    stop
    Multi
    color
    on
    40 Z.
    0=38 Z.
    Soft-
    scroll
    Soft-
    scroll
    Soft-
    scroll
  • Hallo syshack,


    Ich versuche es mal mit einem Beispiel, auf die Gefahr hin, mich lächerlich zu machen:

    Du Dich damit lächerlich machen?! Das ist die bislang eingehendste/verständlichste Erklärung der Materie die ich je sah!
    Ich verwendete bislang and/or nie in dieser Art und Weise - dank Deiner Erklärung fiel es mir aber wie Schuppen von den Augen. Auch wenn ich 'nur' mit dem C64 Basic hin und wieder eine Kleinigkeit mache, so erweiterte Deine Erklärung doch durchaus meinen Horizont. Hut ab und :thnks:

  • @syshack und @Hexworx
    Erstmal riesigen Dank für eure Hilfe und Erklärung

    Am liebsten mag ich ja solche Tabellen:


    Bit 7 6 5 4 3 2 1 0
    Wertig-keit 128 64 32 16 8 4 2 1
    Inversoff 0=on NTSC 0=PAL TED stop Multicolor on 40 Z. 0=38 Z. Soft-scroll Soft-scroll Soft-scroll

    Natürlich versteh ich, was AND, OR und NOT sind. Ich denke, so langsam versteh ich es:


    poke65287,peek(65287)or128+16 = Invers aus + Multicolor an
    Ich les 65287 aus und lösche die Bits 0-3 (1+2+4+8=16) mit OR und setze die Bits 4 und 128 mit AND. So in etwa?


    poke65287,peek(65287)and16or128+16 = 38 Zeichen / Invers aus + Multicolor an
    poke65287,peek(65287)and8or8 = Multicolor aus + Invers an + 40 zeichen

  • Fast.
    "OR (16+128)" setzt die Bits mit den Wertigkeiten 16 und 128, aber
    "AND (1 + 2)" löscht nicht die Bits mit den Wertigkeiten 1 und 2, sondern behält deren alte Inhalte und löscht alle anderen!
    Bei AND muss man also die Bitmaske immer invertieren: Wenn man auf 38 Zeichen umschalten will, braucht man also "poke a, peek(a) and (255 - 8)".


    Oder in kurz:
    OR setzt die Bits, die in der Maske gesetzt sind (und lässt die anderen unverändert).
    AND löscht die Bits, die in der Maske gelöscht sind (und lässt die anderen unverändert).


    ...und Ausdrücke, in denen sowohl OR als auch AND vorkommen, bitte immer klammern. :D

  • EDIT: Tippen hat etwas gedauert, ich hab Post #34 erst danach gelesen. ;)


    Ich kann nur spekulieren, warum Du Dich mit dem Thema schwer tust, aber vielleicht liegt es ja daran, dass Du unbewusst erwartest, dass AND, zu deutsch UND, Dinge "dazu tut":


    X UND Y => "das Ergebnis muss also mehr als X sein!".
    Nein, eben nicht. Tatsächlich kann man mit AND niemals Bits setzen, sondern immer nur löschen oder beibehalten.
    Die Namen der Operationen kommen von den Bedingungen, unter denen Bits im Ergebnis gesetzt sind:
    A OR B => im Ergebnis sind genau die Bits gesetzt, die in A oder in B gesetzt sind (es können also nicht weniger werden). Mit einer Konstante benutzt man die Operation also dann, wenn man Bits setzen will.
    A AND B => im Ergebnis sind genau die Bits gesetzt, die in A und in B gesetzt sind (es können also nicht mehr werden). Mit einer Konstante benutzt man die Operation also dann, wenn man Bits löschen will.

  • Oder in kurz:
    OR setzt die Bits, die in der Maske gesetzt sind (und lässt die anderen unverändert).
    AND löscht die Bits, die in der Maske gelöscht sind (und lässt die anderen unverändert).

    Widersprüchlicher geht's aber auch nimmer ^^ . Demnach müsste man gar nichts Poken bzw. OR-en / AND-en, wenn die Bits vorher schon durch Wunderhand genauso gesetzt / gelöscht sind wie man es vor hat.

  • Nicht immer so vorurteilig oder abwertend. Das habe ich sehr wohl -das ganze binäre z.B., und wie man dies (die 8 bits) in decimal umrechnet weiß ich auch schon ewig- (nur das mit dem inverten müssen beim AND muss ich mir nochmal genauer überlegen).
    Fakt ist aber für mich, dass diese beiden zitierten Sätze an sich sich nunmal & doch eigentlich unwiderlegbar simpel jeweils sich selbst widersprechen - nach meiner logischen Seele / Denkweise [als grundsätzlich gesehen immer logische Schaf/Ziege chin. Sternzeichens ;-)]. Daher finde ich das lustig aber auch interessant, auf welche verschiedenartig denkenden Köpfe man so in der Welt manchmal stößt. :)

  • Das müsste doch z.B. richtig heißen: "OR setzt die Bits, die man selbst sich vorher überlegend in der Maske gesetzt hat (und macht mit den anderen verbleibenden Bits 'automatischer Natur einer solchen Maske' das Gegenteil * )".
    * Wenn das nicht geschehen würde und das "(und lässt die anderen unverändert)" immer passieren würde, würde dabei ja fast immer nur Kokolores dabei herauskommen in der Maske.. u. nur durch Zufall -wenn zufällig vor dem Befehl diese schon so gesetzt bzw. nicht gesetzt sind wie am Ende gewollt- das gewünschte Ergebnis dabei herauskommen. Wie auch immer :) .


    Naja ok, nicht ganz (Korrektur): Ich verstehe zwar, dass "(und lässt die anderen unverändert)" für AND / OR so ganz richtig beschrieben ist/wurde, aber dann muss auch das vor der Klammer im zitierten Satz stehende irgendwo anders formuliert werden. Sonst würde zumind. nach meiner oben erwähnten Seelenlogik ;) ja stets alles gleich bleiben in und mit der 8 bit Maske.