Autor Thema: Struktur auf beliebigen Speicher anwenden  (Gelesen 55307 mal)

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« am: 18. January 2009, 23:44 »
Hi,

ich bin ja gerade dabei C zu lernen, wie ihr ja alle wisst.  :wink: So, nun habe ich irgendwo im Speicher einen speziellen Aufbau. Danach habe ich eine Struktur angefertigt. Jetzt stellt sich mir die Frage, wie ich diese Struktur auch dort anwenden kann.

Also sagen wir der Einfachheit halber hätte ich folgende Struktur:

struct WertePaar
{
u16 Wert1;
u32 Wert2;
};

Also u16 und u32 sind meine Definitionen in der types.h. So, jetzt wäre ab der Speicherstelle 0xBADCOOFE der Aufbau so wie in der Struktur WertePaar. Jetzt würde ich gerne diese Struktur dort anwenden. Wie kann ich das machen?

vielen dank schon mal

bitmaster
In the Future everyone will need OS-64!!!

tarrox

  • Beiträge: 12
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 19. January 2009, 00:46 »
Du erzeugst einen Pointer und gibst diesen dann die Addresse. Jetzt kannst du mit -> auf die Member zugreifen.

WertePaar *NAME; //erzeuge Pointer
NAME = 0xBADC00FE; //Gib dem Pointer die gewollte Adresse
NAME->Wert1 = 10; //Wert1 wird geändert
NAME->Wert2 = (u32)NAME->Wert1; //Wert2 wird geändert
« Letzte Änderung: 19. January 2009, 01:01 von tarrox »

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 19. January 2009, 02:17 »
Die erste Zeile von tarrox klappt in C nicht (dafür aber in C++), die zweite sollte in beiden nicht gehen. (Compiler aus dem Kalten Krieg sehen das vielleicht etwas lockerer.) So klappts immer:
struct WertePaar *NAME; // <-- das struct gehört zum typen dazu
NAME = (struct WertePaar *) 0xBADC00FE; // <-- casten, damit der Compiler nicht weint

Wenn du struct nicht schreiben willst, befrage die Wissenquelle deiner Wahl nach typedef.
« Letzte Änderung: 19. January 2009, 02:20 von PorkChicken »
Dieser Text wird unter jedem Beitrag angezeigt.

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #3 am: 19. January 2009, 21:06 »
Jo, scheint zu funktionieren. Vielen dank euch beiden.
In the Future everyone will need OS-64!!!

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #4 am: 25. January 2009, 23:33 »
So, und weiter gehts mit der Fragerei. Also in der Variable multiboot_address steht die Adresse der multiboot (wer hätte es gedacht ^^). So, dann habe ich eine Struktur, die ich multiboot_info genannt habe. In meiner kernel.c habe ich dann das stehen:

struct multiboot_info *boot_info;
boot_info = (struct multiboot_info *) multiboot_address;

Jetzt kann ich ja mittels:

boot_info->ELEMENT
Darauf zugreifen. Alles schön und gut. Aber jetzt möchte ich außerhalb der kernel.c darauf zugreifen. Also ich habe jetzt eine mm.c in der ich auch mittels

boot_info->ELEMENT
darauf zugreifen möchte. Aber das geht ja nicht. Dann habe ich es mit extern versucht. Aber das funktioniert auch nicht. Ich weiß nicht was ich genau hinter extern schreiben soll. Also der muss ja den Aufbau der Struktur kennen und wo sich der ganze Krempel befindet. Also eher was für C Profis und nicht so Noobs wie mich.  :cry: Von daher wollte ich fragen ob ihr mir da evtl. helfen könnt.

thx

bitmaster
In the Future everyone will need OS-64!!!

Termite

  • Beiträge: 239
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 26. January 2009, 10:20 »
Moin

extern heist so viel wie das die definition der Variable in einer anderen übersetzungseinheit erfolgt und nicht in der Aktuellen. Somit ein hinweis auf den Compiler/linker das er die variable trotzdem verwenden darf, und erst der Linker im hinterher angibt wo er das ding wirklich finden kann.

So als erstes sollte man sich in C angewöhnen 2 H Dateien zu verwalten. eine für den öffentliche teil, der andere für den Internen krempel, der auser im Modul sonst keinen was angeht. Zusätzlich zu den .C Dateien

MOD_C1.H öffentlicher teil des Moduls
typedef struct multiboot_info
{
    unsigned long int ELEMENT;
    unsigned long int ELEMENT1;
    unsigned long int ELEMENT2;
} multiboot_info_Type;

extern struct multiboot_info *boot_info;
/* oder alternative
extern multiboot_info_Type * boot_info;
*/


MOD_C1.C  Die implementierunt des Moduls
#include "MOD_C1.H"
boot_info = (struct multiboot_info *) multiboot_address;
/* oder alternative
boot_info = (multiboot_info_Type *) multiboot_address;

*/

ABC_Cx.C  ein anderes Modul
#include "MOD_C1.H"

boot_info->ELEMENT;


gruss

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #6 am: 26. January 2009, 20:33 »
Hi, vielen dank für deine Mühe.

Aber gcc meckert:

Zitat
MOD_C1.O: In function `main':
MOD_C1.C:(.text+0x1c): undefined reference to `boot_info'
MOD_C1.C:(.text+0x38): undefined reference to `boot_info'
MOD_C1.C:(.text+0x54): undefined reference to `boot_info'
ABC_Cx.O: In function `init_phys_mem':
ABC_Cx.C:(.text+0x4): undefined reference to `boot_info'

hmm...
In the Future everyone will need OS-64!!!

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #7 am: 26. January 2009, 20:39 »
in die MOD_C1.C muss noch
struct multiboot_info *boot_info;
die Definition von boot_info.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #8 am: 26. January 2009, 21:40 »
in die MOD_C1.C muss noch
struct multiboot_info *boot_info;
die Definition von boot_info.
Dann sagt mir gcc noch:

Zitat
ABC_Cx.O: In function `init_phys_mem':
ABC_Cx.C:(.text+0x4): undefined reference to `boot_info'

Und wenn ich in der ABC_Cx.C einfach auch

struct multiboot_info *boot_info;
schreibe, dann stimmen dort die Werte nicht.  :-(

bitmaster
In the Future everyone will need OS-64!!!

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #9 am: 26. January 2009, 22:30 »
Wenn du das was du momentan hast irgendwo hochlädst würde ich es mir ansehen und könnte dir wahrscheinlich sagen wo das Problem liegt.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #10 am: 26. January 2009, 23:24 »
OK, also ich habe eine multiboot.h, in der steht:

struct multiboot_info
{
u32 blabla
usw.
};

extern struct multiboot_info *boot_info;

Dann habe ich eine kernel.c, in der steht:

#include <multiboot.h>

void main(u32 multiboot_address, u32 multiboot_magic)
{
//clear screen
ClearScreen();

struct multiboot_info *boot_info;
boot_info = (struct multiboot_info *) multiboot_address;

test();

usw.
}

Dann habe ich eine test.c, in der steht:

#include <multiboot.h>

void test(void)
{
asm ("mov %0, %%eax" : : "m" (boot_info->ELEMENT));

while (1);
}

Dann lasse ich gcc compilieren und habe dann eine kernel.o und eine test.o. Mittels ld möchte ich die dann "zusammenlinken". Aber ld sagt dann:

Zitat
test.o: In function `test':
test.c:(.text+0x4): undefined reference to `boot_info'

bitmaster
In the Future everyone will need OS-64!!!

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 26. January 2009, 23:38 »
Du hast mit extern struct multiboot_info *boot_info; nur den Zeiger deklariert, aber nicht definiert. Das heißt es gibt keinen zugeordneten Speicherbereich. Die Lösung ist also eine Definition mittels struct multiboot_info *boot_info;Die Zeile könnte z.B. in kernel.c unter den headern stehen.
Dieser Text wird unter jedem Beitrag angezeigt.

Termite

  • Beiträge: 239
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 26. January 2009, 23:38 »
Nabend

und asche auf mein haupt,

in deiner kernel.c sollte noch die zeile von bluecode rein. ups is ja schon drinnen, nur im falschen kontext
#include <multiboot.h>

// muss global deklarirt werden! kann von allen funktionen dieser C Datei
// verwendet werden. wenn ein extern existiert auch von anderen
// übersetzungseinheiten. werden vom linker in den Data bereich abgelegt.

struct multiboot_info *boot_info;

// ein static reduziert die gültigkeit einer globalen variablen auf genau die C
// Datei in der sie definiert wurde. extern tut dann nicht mehr!

void main(u32 multiboot_address, u32 multiboot_magic)
{
//clear screen
ClearScreen();

// was hier deklariert wird hat nur gültigkeit inerhalb dieser funktion
// und sonst niergens nennen sich auch lokale variablen und werden
// meist auf dem Stack / heap angelegt.
boot_info = (struct multiboot_info *) multiboot_address;

test();

usw.
}

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 26. January 2009, 23:40 »
Hm, also ich mein das was Termite sagt ^^
Dieser Text wird unter jedem Beitrag angezeigt.

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #14 am: 26. January 2009, 23:50 »
Ah  :-D und siehe da es tut.  :-o

Jo, ich muss mich noch ein wenig an dieser (HOCH)sprache gewöhnen. ^^

vielen dank euch  :-)

bitmaster
In the Future everyone will need OS-64!!!

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #15 am: 28. January 2009, 19:11 »
Und da bin ich wieder.  :-D

So, es geht wieder um Strukturen. Hier ein Beispiel aus dem Internet:

#include <stdio.h>
 
struct person {
        short gewicht;
        short alter;
        short groesse;
};
 
int main()
{
        struct person p[3];
 
        p[0].gewicht = 70;
        p[0].alter = 22;
        p[0].groesse = 182;
 
        p[1].gewicht = 88;
        p[1].alter = 77;
        p[1].groesse = 166;
 
        p[2].gewicht = 95;
        p[2].alter = 50;
        p[2].groesse = 190;
 
        return 0;
}

Jetzt habe ich aber nicht 3 sondern X Personen. Sprich die Anzahl der Personen steht in einer Variable und wird erst zur Laufzeit ermittelt. Ist es dann möglich statt

struct person p[3];
einfach

struct person p[VARIABLE];
zu schreiben? Also mein gcc macht da irgendwas komisches wenn ich es so mache. Also zumindest kann ich den disassemblierten Code nicht nachvollziehen.

thx

bitmaster
In the Future everyone will need OS-64!!!

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 28. January 2009, 19:35 »
Hi,

das Problem ist, dass C keine dynamischen Arrays unterstützt (zumindest nicht ohne viele Tricks).
Du könntest dir eine Liste schreiben.
Das ist das einfachste.

Gruß
rizor
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #17 am: 28. January 2009, 19:39 »
Hi,

das Problem ist, dass C keine dynamischen Arrays unterstützt (zumindest nicht ohne viele Tricks).
Du könntest dir eine Liste schreiben.
Das ist das einfachste.

Gruß
rizor
THX

Hmm... schade, aber was meinst du mit "Liste"?

bitmaster
In the Future everyone will need OS-64!!!

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #18 am: 28. January 2009, 19:41 »
Was bitmaster will, ist ein statisches Array auf dem Stack, dessen Größe zur Laufzeit bestimmt wird. Und das geht mit gcc (ist aber eine gcc-Erweiterung, wenn ich mich nicht irre).

void test(int x)
{
    int blubb[x];
    // ...
}
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #19 am: 28. January 2009, 19:44 »
struct linstenelement{
    struct listenelement *vorgaenger;
    struct person mensch;
    struct listenelement *nachfolger;
}

Das wäre eine doppelt verkettete Liste.
Dann bräuchtest du nur noch einen Pointer, der auf ein Element zeigt.
Dann gibt es zwei möglichkeiten:
1. Du machst eine doppelt verkettete Liste also an einem Element ist der Vorgaenger = NULL
und an einem Elemenet der Nachfolger  = NULL
2. Du baust eine Ringliste auf. also irgendwann zeigt das letzte Element auf das erste.
Da musst du halt nur aufpassen, dass du nicht in eine Endlosschleife läufst.

Was bitmaster will, ist ein statisches Array auf dem Stack, dessen Größe zur Laufzeit bestimmt wird. Und das geht mit gcc (ist aber eine gcc-Erweiterung, wenn ich mich nicht irre).

void test(int x)
{
    int blubb[x];
    // ...
}
Achso, ich dachte es geht einzig und allein um die Arrays.

Gruß
rizor
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

 

Einloggen