Funktion als Makro



  • Hallo hallo,

    wie könnte die folgende Funktion als Makro aussehen?

    int getIt( uint32_t addr){
        uint32_t *p = addr;
        return *p;
    }
    

    Danke



  • Wenn du die Funktion zusammenstreichst, bleibt eigentlich nur *addr übrig.
    Genauer (int)(*(uint32_t*)(addr))

    Da *p und der Rückgabetyp der Funktion unterschiedlich sind, bleibt die Frage ob das so richtig und/oder sinnvoll ist.



  • Spitze!

    Und wie würde das hier aussehen?

    void set( uint32_t addr, uint32_t value){
    
        uint32_t *p = (uint32_t*) addr;
        *p = value;
    }
    


  • olpo schrieb:

    Und wie würde das hier aussehen?

    *( (uint32_t*) addr ) = value 🙄

    DirkB schrieb:

    [...] bleibt die Frage ob das so richtig und/oder sinnvoll ist.



  • Das erinnert doch stark an PEEK und POKE von Basic.

    Eine Suche nach peek und poke makro C liefert als Erstes http://tigcc.ticalc.org/doc/peekpoke.html

    Aber wenn du das brauchst, hast du die Problemlösung nicht richtig für C umgesetzt.



  • oh, ja. Ich hab' damals mit QBasic nicht gepoked ... und am TI92 konnt ich noch kein C ... dafür TI-BASIC 🤡



  • Es gibt tatsächlich einige Anwendungsbereiche, bei denen dieser Lösungsansatz valid ist: Emulatoren/Virtualisierte Umgebungen - bei denen Code, den du nicht geschrieben hast, ausgeführt werden muss. Du ließt den Opcode zusammen mit seinem Parameter/seinen Parametern ein, das kann auch eine Adresse sein. Meistens ist das aber erst mal nur ein unsigned int Aber wie stellst du sicher, dass die Adresse so gültig ist?

    Geht halt nur über einen Wrapper, der vor jedem Zugriff prüft, ob der Zugriff so in Ordnung ist. Operatorenüberladung kennen wir in C ja nicht ...



  • Ein Emulator muss normalerweise den Adressraum des emulierten Geräts emulieren. Die Adressen des emulierten Geräts einfach als Zeiger interpretieren funktioniert da nicht.
    Das geht nur, wenn das emulierte Gerät kein definiertes Adress-Layout hat, und man über andere Mittel irgendwie sicherstellen kann dass der Zugriff "safe" ist.

    Das selbe gilt für VMs (ala VMware/VirtualBox/QEmu).

    Bzw. ...
    Wenn ein Teil des Opcode eine absolute Adresse ist, dann impliziert das ja eigentlich schon dass es ein Adresslayout gibt welches man emulieren muss -- sonst könnten ja keine absoluten Adressen im zu-emulierenden Code stehen.
    Und wenn es bloss ein Offset ist (also eine relative Adresse), dann schreibt man ptr[offset] und braucht wieder keinen integer -> pointer Cast.



  • hustbaer schrieb:

    Wenn ein Teil des Opcode eine absolute Adresse ist, dann impliziert das ja eigentlich schon dass es ein Adresslayout gibt welches man emulieren muss -- sonst könnten ja keine absoluten Adressen im zu-emulierenden Code stehen.
    Und wenn es bloss ein Offset ist (also eine relative Adresse), dann schreibt man ptr[offset] und braucht wieder keinen integer -> pointer Cast.

    Nein, das stimmt so auch nicht. Bestes Beispiel (weil mir das gerade einfällt) ist der alte Super Nintendo. Die CPU, ein 65816, hatte einen 24-Bit-Adressbus, über den auf verschiedene Teile des Speichers (WRAM, SRAM, ROM, den 8-Bit-Bus von APU und der PPUs usw.) zugegriffen werden konnte. Aber welche Adressen jetzt gemappt wurden, hängt vom Adressdekodierer auf der Cartridge ab - und wenn das ROM nicht den vollen Speicher im 0x800000 - 0xFFFFFF ausgenutzt hat (mit LoROM und HiROM kannst du bis zu 4 MB adressieren, aber viele ROMs waren kleiner), dann war z.B. ab 0xDFFFFF (3 MB HiROM) nichts mehr definiert, was beim Zugriff rauskommt.

    Vielleicht war es doch definiert, vom AD-Chip. Aber ein Emulator muss den halt auch emulieren, oder er macht das Mapping in Software. Und wenn ein Speicherbereich über 0xDFFFFF erfolgt, dann muss er das abfangen oder darauf reagieren. Weil die CPU aber Opcodes versteht, bei denen noch drei Bytes Adresse (0xFFFFFF) mitgeliefert werden können, musst du das selbst prüfen.

    Man kann es sich auch ganz einfach machen und die jeweiligen Seiten einfach mit reserviertem Speicher füllen, sodass dann invalide Speicherzugriffe nicht so schlimm sind. Das wäre dann nicht so, wie die Originalmaschine sich verhalten hätte, aber als Maßnahme vor Schutzverletzungen würde ich das ohne Murren akzeptieren. Hilft aber nicht beim Zugriff auf die Hardwareregister und den 8-Bit-Bus, das musst du manuell auflösen -> Wrapper.



  • Nachtrag:
    Hab mich vertan bei der Speicherblockgröße. Von Bank 0xC0 bis 0xFF wird gemappt, das sind 0x40. Eine Bank sind 64 KB, 0x10 davon sind 1 MB. Bis Bank 0xD0 sind wir nicht bei 3 MB, sondern nur bei 2 MB.


Anmelden zum Antworten