1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Funktionsweise von Pointern mit Offsets

Discussion in 'Tipps & Tricks' started by hoschi111, Nov 1, 2012.

  1. hoschi111

    hoschi111 Administrator Staff Member Administrator

    Joined:
    Dec 19, 2017
    Messages:
    1,445
    Likes Received:
    0
    Hallo zusammen!
    Für den Server Control Pro brauchte ich dringend Wissen über Pointer und Offsets.
    Leider musste ich mit Erschrecken feststellen, dass es keine allgemein verständlichen Erklärungen dazu gibt, die gleichzeit noch erklären, wie Adressen eigentlich auf andere Adressen "zeigen" können.

    1.)
    Wie können Adressen auf andere Adressen zeigen?
    Um es Allgemein auszudrücken: Adressen sind Speicherstellen. Wie Schließfächer. Dort kann man Werte bzw. Informationen hineinschreiben.
    Des Weiteren muss man sich im Klaren sein, dass die Darstellung dieser Informationen nebensächlich ist. Am Ende wird sowieso alles in Binärcode umgewandelt.

    Eine Adresse kann also jede Information speichern, nur ist auf Grund der Darstellung nicht immer klar zu erkennen, was der gespeicherte Wert "uns sagen möchte."
    Das heißt jetzt zum Schluss: Speicheradressen können auch wieder andere Adressen als Wert haben. => Sie zeigen auf eine neue Adresse. => Pointer!

    2.)
    Aber, was ist nun ein Offset?
    Offsets, das sind "Adressschieber". Sie schieben eine gelesene Adresse eines Pointers (Pointer enthält bei Multi-Level wieder eine Adresse).
    Ein Pointer könnte zum Beispiel auf eine Adresse zeigen, die gar keinen Sinn machen würde ohne Offset.
    Beispiel:
    Ohne Offset: Pointer => zeigt auf => Adresse => zeigt auf Schwachsinn
    Mit Offset: Pointer => zeigt auf => Adresse + Offset [hier kommt das Offset ins Spiel. Das Offset addiert / subtrahiert nun einen bestimmten Wert auf die Adresse. (Aus Adresse 0x934FA0 wird mit Offset "0x8" => 0x934FA8)] => zeigt auf eine nützliche neue Adresse

    Kleine grafische Darstellung:
    [​IMG]


    Habt ihr noch Fragen? Versteht ihr etwas noch nicht?
    Dann kommentiert doch einfach hier ;)
     
  2. krusty

    krusty New Member

    Joined:
    Sep 8, 2012
    Messages:
    182
    Likes Received:
    0
    Gut, dann erweitere ich mal das Tutorial um den Sinn von Offsets in Bezug auf Strukturen im Speicher.

    Im Speicher stehen oftmals Strukturen bzw. Klassen, d.h. dass Informationen hintereinander aufgelistet werden.
    Wenn man Zeiger findet, zeigen diese meist auf den Anfang der Struktur/Klasse/Enum, what ever.

    ein Beispiel, wir haben eine Struktur im Speicher:
    Code:
    0x00122 0
    0x00123 200
    0x00124 'k'
    0x00125 'r'
    0x00126 's'
    0x00127 't'
    0x00128 'y'
    0x00129 0
    0x0012A 4
    
    Schauen wir uns das Beispiel an, im Speicher stehen untereinander Informationen.
    An erste Stelle steht eine 0, damit können wir nichts anfangen.
    An zweiter stelle steht die Lebensanzahl, 200
    Von der dritten bis zut achten Stelle steht der Name des Spielers
    Dann kommt eine 0
    Dann kommt das Level des Spielers.

    Angenommen wir finden einen Pointer:
    Code:
    DWORD p = 0x001337
    , dieser Zeigt auf den Anfang unserer Struktur,
    wenn wir also den Inhalt von p auslesen, so erhalten wir 0x00122, beispiel:
    Code:
    DWORD p = 0x001337
    DWORD structAnfang = readMemoryDword(p)
    
    in structAnfang steht nun 0x00122. Wenn wir den inhalt von 0x00122 auslesen, erhalten wir aber nur eine 0, damit können wir nicht viel anfangen. Wir möchten gerne das Leben des Spielers und den Namen auslesen, also müssen wir ein sogenanntes Offset addieren.
    Für das Leben haben wir das Offset 0x01
    Für den namen haben wir das Offset 0x02
    Pseudocode:
    Code:
    CONST lebenOffset = 0x01
    CONST nameOffset = 0x02
    DWORD p = 0x001337
    DWORD structAnfang = readMemoryDword(p)
    BYTE Leben = readMemoryByte(structAnfang + lebenOffset)
    String Name = readMemoryString(StructAnfang + nameOffset)
    
    Zusammenfassung:
    Wir haben einen Pointer auf den Anfang einer Struktur. Am Anfang stehen aber keine interesseanten Informationen, sondern irgendwo darunter.
    Darum addieren wir Offsets zu der Anfangsadresse der Struktur um an die Informationen zu kommen.

    Warum gibt es Multilevelpointer ?
    Wer sich ein bisschen mit OOP auseinandersetzt, weiß, dass ein Objekt in einer Programmiersprache meist nur ein Zeiger auf das Objekt ist.
    Also immer, wenn wir eine Eigenschaft eines Objektes aufrufen (TextBox1.text = "123") oder (this->getHandle()), so arbeiten wir über den Zeiger des Objektes.
    Damit kann die Programmiersprache einfach besser arbeiten, bzw es besser übersetzen.

    Oftmals haben Objekte wieder Objekte:
    Code:
    TextBox1.location
    In diesem Beispiel hat das Objekt TextBix1 wieder ein Objekt mit dem Namen Location.

    Worauf ich hinaus möchte, manchmal kommen in Strukturen/Klassen im Speicher Adressen vor, die wieder auf andere Objekte verweisen, z.B. könnte das Textbox1Objet im speicher so aussehen:

    Code:
    0x00120 'TextBox1'
    0x00128 0
    0x00129 8
    0x0012A 0x01337
    0x0012E 200
    0x00130 100
    
    An der ersten Stelle steht der Name des Objektes,
    danach kommt eine 0
    danach kommt die Läge des Namen (8 Buchstaben)
    danach kommt eine Adresse, die auf das Location Objekt zeigt
    danach kommt z.B. die Weite der Textbox in Pixeln
    danach kommt z.B. die Höhe der Textbox in Pixeln

    Der Adressbereich, an dem Location liegt könnte jetzt wieder so aussehen:
    Code:
    0x01337 0
    0x01338 134
    0x01339 200
    ...
    
    An der ersten Stelle steht eine 0, nicht interessant,
    dann kommt die X Koordinate
    dann kommt die Y Koordinate.

    Angenommen wir haben einen Pointer p, der auf unser Textbox Objekt/Struktur zeigt:
    Code:
    DWORD p = 0x00120
    Wir wollen jedoch an die X Koordinate der Textbox, Die Adresse der LocationStruktur liegt 10 Bytes nach dem Beginn der TextboxStruktur:
    Code:
    CONST LocationOffset = 10
    DWORD LocationAdresse = readDrowd( p + LocationOffset )
    
    Jetzt haben wir die Startadresse der Locationstruktur.
    An dieser Adresse (0x01337) steht aber eine 0, damit können wir nichts anfangen, wir wollten an die X Koordinate, die ist 1 Byte hinter der Startadresse:
    Code:
    CONST xCoordinateOffset = 1
    int xKoordinate = readInd(LocationAdresse + xCoordinateOffset )
    
    Somit haben wir einen 1 Levelpointer durchlaufen.
    1. TextBoxStartAdresse + OffetFürLocation = LocationAdresse
    2. LocationAdresse + offsetFürXKoordinate = xKoordinate
    Oftmals findet man Pointer mit viel Mehr leveln, z.b.:
    Code:
    SpielObjekt->Liste aller Spielobjekte->Liste aller Spieler->Erster Spieler ->HauptWaffe -> Name
     
  3. Dr@ke

    Dr@ke New Member

    Joined:
    Jul 10, 2012
    Messages:
    743
    Likes Received:
    2
    Nice ;)
    Schönes Tuts :D
    (ddie man auch versteht... :D)