Speicherung von Variablen



  • Also wenn ich dass das richtig verstehe, und ich mir einen integer mit zum beispiel 5 initialisiere, kann ich sozusagen noch nicht davon ausgehen, dass dieser Wert wirklich irgendwo im RAM steht oder? Kann ich davon ausgehen, wenns im Assembler-Code steht? Das ist nur hypothetisch gefragt.



  • @zhavok sagte in Speicherung von Variablen:

    Also wenn ich dass das richtig verstehe, und ich mir einen integer mit zum beispiel 5 initialisiere, kann ich sozusagen noch nicht davon ausgehen, dass dieser Wert wirklich irgendwo im RAM steht oder?

    Genau. zB: hier steht direkt das Ergebnis von 5 * value als Anweisung im Codesegment: mov esi, 25.

    @zhavok sagte in Speicherung von Variablen:

    Kann ich davon ausgehen, wenns im Assembler-Code steht?

    In der Regel schon.



  • Nein, davon kannst du nicht ausgehen. Wenn du eine Variable nur initialisierst wird der Compiler die zum Beispiel weg optimieren.
    Generell abstrahieren Hochsprachen so weit, dass der Code des Entwicklers auf unterschiedlicher Hardware die gleichen Ergebnisse liefert.
    Wenn man es genau nimmt, ist Assembler schon eine Abstraktion des eigentlichen Maschinencode.

    Wenn du mit Assembler eine 5 an eine Speicherstelle schreibst kannst du dir (hoffentlich) sicher sein, dass an der Speicherstelle eine Bit-Kombination steht, die genau der Assembler wieder als 5 interpretieren kann.


  • Mod

    @zhavok sagte in Speicherung von Variablen:

    Also wenn ich dass das richtig verstehe, und ich mir einen integer mit zum beispiel 5 initialisiere, kann ich sozusagen noch nicht davon ausgehen, dass dieser Wert wirklich irgendwo im RAM steht oder? Kann ich davon ausgehen, wenns im Assembler-Code steht? Das ist nur hypothetisch gefragt.

    Welche Anweisung soll dafür denn im Assemblercode stehen?

    MOV irgendeine_adresse, 5
    

    ?
    Vielleicht steht so etwas da drin, vielleicht auch nicht. Schau hier: https://godbolt.org/g/iVvMFN
    Aber gerade bei diesen einfachen Beispielen hat man halt sehr oft, dass eine Variable gar keine konkrete Adresse im Speicher ist, sondern dass sie vollständig in der Logik des Gesamtprogramms aufgeht. Obiges Beispiel hinter dem Link ist sehr bewusst so gewählt, dem Compiler solche Optimierungen unmöglich zu machen. Eine kleine Änderung und alles ist komplett weg:
    https://godbolt.org/g/Qckf24
    Oder etwas komplexer:
    https://godbolt.org/g/nh8PF8
    Weder i noch result noch die 0 oder die 5 existieren hier irgendwo im Maschinencode. Sie sind bloß indirekt da, insofern als dass das Programm sich exakt genau so verhält, als wären sie da gewesen. Und eax ist auch nirgendwo im RAM, sondern das ist eine Speicherzelle in der CPU. Der Wert bleibt dort bloß ganz flüchtig, bis der aufrufende Code der Funktion wahrscheinlich direkt damit weiter arbeitet, ohne dass der Wert 10 jemals auch nur die CPU verlässt.


  • Mod

    @swordfish sagte in Speicherung von Variablen:

    Genau. zB: hier steht direkt das Ergebnis von 5 * value als Anweisung im Codesegment: mov BYTE PTR [rsp+15], 10.

    Da rechnest du besser noch einmal nach 🙂

    Das Ergebnis steht in Zeile 3: mov esi, 25. Das mov BYTE PTR [rsp+15], 10 ist das '\n'.



  • @seppj sagte in Speicherung von Variablen:

    Da rechnest du besser noch einmal nach

    Ich sag nichts, wenn Du nichts sagst 👍 = ? :face_with_stuck-out_tongue_winking_eye:



  • Was bekomme ich dann also zurück, wenn ich zum Beispiel folgendes schreibe:

    #include <iostream>
    
    int main() {
    	int val = 18;
    	std::cout << &val << std::endl;
    }
    

    Bisher bin ich immer davon ausgegangen, dass es sich um die Adresse im Arbeitsspeicher handelt :smiling_face_with_open_mouth_cold_sweat: .
    Und warauf greife ich eigentlich mit

    WriteProcessMemory(handle, (LPVOID)0x861E74, &val, sizeof(val), 0);
    

    zu? Fragen über Fragen 😂



  • @zhavok sagte in Speicherung von Variablen:

    Was bekomme ich dann also zurück, wenn ich zum Beispiel folgendes schreibe:

    Wenn Du die Adresse einer Variable nimmst, dann "zwingst" Du den Compiler, auch Speicher dafür zu besorgen.

    @zhavok sagte in Speicherung von Variablen:

    Und warauf greife ich eigentlich mit WriteProcessMemory() zu?

    Das steht in der Dokumentation der Funktion.



  • @seppj sagte in Speicherung von Variablen:

    Welche Anweisung soll dafür denn im Assemblercode stehen?

    MOV irgendeine_adresse, 5
    

    ?

    Na selbst dann kommts evtl. nie in den RAM, das wuerde diesen Befehl sonst um Groessenordnungen ausbremsen.



  • @tggc sagte in Speicherung von Variablen:

    @seppj sagte in Speicherung von Variablen:

    Welche Anweisung soll dafür denn im Assemblercode stehen?

    MOV irgendeine_adresse, 5
    

    ?

    Na selbst dann kommts evtl. nie in den RAM, das wuerde diesen Befehl sonst um Groessenordnungen ausbremsen.

    Naja ich denke man kann bei Überlegungen dieser Art die diversen Caches schonmal vernachlässigen.



  • Aber man sollte die Prozessor-Register (d.h. bes. "Datenregister") hierbei noch erwähnen (wie man auch bei den geposteten Assembler-Codes sieht), d.h. bei der Optimierung werden lokale Variablen sowie Funktionsparameter (so gut es geht) auf diese verteilt, anstatt im RAM (z.B. Stack) abgelegt zu werden. Dafür gab es früher ja explizit in C und C++ das registerSchlüsselwort, bevor die Compileroptimierungen selber diese Entscheidung übernommen haben).



  • @hustbaer sagte in Speicherung von Variablen:

    @tggc sagte in Speicherung von Variablen:

    @seppj sagte in Speicherung von Variablen:

    Welche Anweisung soll dafür denn im Assemblercode stehen?

    MOV irgendeine_adresse, 5
    

    ?

    Na selbst dann kommts evtl. nie in den RAM, das wuerde diesen Befehl sonst um Groessenordnungen ausbremsen.

    Naja ich denke man kann bei Überlegungen dieser Art die diversen Caches schonmal vernachlässigen.

    Also oben war konkret die Frage obs im RAM steht. Entweder wir sind hier auf konzeptioneller Ebene und sagen, jede Info liegt in einem Art "RAM" - wir koennen aber nicht wissen wo der physikalisch ist. Oder wir unterscheiden hier genauer, dann sind wir aber mit Register/RAM aber noch lange nicht fertig - das wollte ich hier nur andeuten und das ist auch relativ wichtig wenn man per ASM programmiert.



  • @TGGC
    Naja gut da ist jetzt die Frage wie man "RAM" definiert.

    Ich meine auf jeden Fall: man kann auch wenn man Assembler diskutiert oft vernachlässigen dass es mehrere Cache-Ebenen zwischen der CPU und dem letztendlichen Hauptspeicher gibt. Weil die transparent sind. Dort wo der C(++) Programmierer sich meist nicht weiter darum kümmern muss ob seine Variable jetzt in einem Register liegt oder im Speicher oder gar nirgendwo, dort muss der Assembler-Programmierer sich meist nicht darum kümmern ob etwas in einem der Caches liegt oder (nur) im Hauptspeicher. Meist reicht einfach die Info dass es im Speicher an Adresse so-und-so liegt.

    Oder anders gesagt: es gibt nicht nur "die" konzeptionelle Ebene, es gibt davon viele. Eben auch die wo der Assembler Programmierer nur mit dem Konzept Speicher arbeitet und ignorieren kann wie das mit den Caches evtl. gehen könnte.

    Für Performance-Optimierung ist es natürlich wichtig zu wissen wie Caches üblicherweise funktionieren, aber ansonsten muss man mMn. nichtmal wissen dass es sie überhaupt gibt. Zumindest nicht so lange man Userland Code schreibt.



  • @hustbaer
    Ja, natuerlich. Wir sind hier aber im C++ Forum, also sehe ich wenig Sinn eine Frage nun gerade nur aus Sicht eines Assemblerprogrammierers zu beantworten.

    Und wie ich schon sagte, stimmt das auch für ASM nicht. Denn "in Adressraum schreiben" bedeutet auch in Assembler nicht automatisch "in RAM schreiben", da einem recht schnell das Konzept begegnet, in den normalen Adressraum andere Sachen einzublenden.



  • Ich merke schon. So einfach wie ich mir das vorgestellt habe läuft das leider nicht mit Variablen und dem RAM. Vielen Dank für eure Antworten.



  • @tggc sagte in Speicherung von Variablen:

    Und wie ich schon sagte, stimmt das auch für ASM nicht. Denn "in Adressraum schreiben" bedeutet auch in Assembler nicht automatisch "in RAM schreiben", da einem recht schnell das Konzept begegnet, in den normalen Adressraum andere Sachen einzublenden.

    Wenn man die Adresse von einer Funktion ala malloc bekommen hat, und dann da reinschreibt, dann bedeutet das schon "in RAM schreiben". Sonst ist irgendwo irgendwas gröber schief gelaufen.

    Mir geht's aber einfach nur darum dass es viele "Zwischenebenen" gibt auf denen man sinnvoll diskutieren/argumentieren kann. Und dass man nicht von komplett abstrakt gleich zu einer bis ins letzte detailierten Beschreibung der Hardware wechseln muss. Bzw. mMn. ist das sogar kaum jemals sinnvoll. Schon alleine deswegen weil man die Hardware meist gar nicht so genau kennt.

    Ist aber auch nicht so wichtig 🙂


Anmelden zum Antworten