Zeiger in C auf einem 32-Bit System

Gast #502453
Lesenswert?

Warum reserviert C bei einem Integer-Zeiger  4 Adressen und nicht eine 
einzige Adresse ( 32-Bit breiter Datenbus )?
Gibt es einen 8-Bit bzw. 32-Bit Modus?
Wie kann ich zwischen den beiden Moden umschalten?

System:    PC104 Cool LiteRunner
Betriebssystem:   Linux Kernel 2.6.16 mit Xenomai Patch
Prozessor:     AMD GX 466

Warscheinlich werden sich jetzt einige an den Kopf fassen und sagen man 
ist der doof :-) aber das kenn ich auch.
Danke schon mal!
Gast #502491
Lesenswert?

> Warum reserviert C bei einem Integer-Zeiger  4 Adressen und nicht eine
> einzige Adresse ( 32-Bit breiter Datenbus )?

Verstehe nicht, was du meinst. Wo werden 4 Adressen reserviert? Ein 
Zeiger kann nur die Adresse eines einzelnen Objekts enthalten. Er hat 
auch nur eine Adresse.

> Gibt es einen 8-Bit bzw. 32-Bit Modus?

Nein. Was soll der denn machen?

> Warscheinlich werden sich jetzt einige an den Kopf fassen und sagen man
> ist der doof :-)

Nein. Man wird ja nicht allwissend geboren. Ich kratz mich nur am Kopf 
und versuche, die Frage zu verstehen. ;-)
#502494
Lesenswert?

ZUnächst mal sollten wir klären, wie du
zu der Aussage 'es werden 4 Adressen reerviert' kommst.

Ein Zeiger belegt auf einem 32 Bit System meistens 4 Byte.
Ein int belegt in einem 32 Bit System ebenfalls 4 Byte.

Auch wenn du auf einem 32 Bit System bist, die kleinste
addressierbare Einheit ist immer noch das Byte.
Gast #502499
Lesenswert?

Kleines Beispiel was ich meine:

#include<stdio.h>

main()
         {
    int i;
    int mem[5];

    for (i=0; i < 5; i++)
      printf("adr: %x\n", &mem[i]);

          }

Ausgabe:

adr: bfcf40c0
adr: bfcf40c4
adr: bfcf40c8
adr: bfcf40cc
adr: bfcf40d0

Wie man erkennt beträgt das Inkrement 4. Da ich aber eigentlich einen 
32-Bit Datenbus habe sollte doch ein Inkrement von 1 ausrechend für 
einen Integer sein.
Oder sehe ich da etwas falsch?
Gast #502507
Lesenswert?

Ja, das siehste grottenfalsch. Die kleinste_ _adressierbare_ _Einheit 
bei diesem System ist - wie bei vielen anderen auch - das Byte (8 Bit). 
Ein Integer ist bei diesem Compiler 32 Bit lang, benötigt also 4 Bytes. 
Dementsprechend ist die Adress-Differenz zwischen zwei 
aufeinanderfolgenden Elementen dieses Arrays genau 4. Probiere das Ganze 
mit short aus; Du wirst ein Inkrement von 2 erhalten; bei char sinkt das 
Inkrement auf 1.

Bernhard
Gast #502578
Lesenswert?

> Die kleinste_ _adressierbare_ _Einheit bei diesem System ist - wie
> bei vielen anderen auch - das Byte

Kunststück. So ist das Byte in der Regel definiert.

> (8 Bit).

Das meistens auch, ja.

@Armin:

Überlege mal: Wenn bei int das Inkrement 1 ist, wie groß müßte es dann 
für Typen sein, die kleiner als int sind?
#502760
Lesenswert?

Armin wrote:
> Ok wenn dem so ist, dann kann aber die Adresse die ich in diesem
> Beispiel erhalte keine real existierende Adresse sein.?

Das ist nicht die Adresse auf dem Adressbus, sondern eben die 
Byte-Adresse.

Du kannst auf den meisten 32Bit-CPUs auch einen 32bit-Wert an die 
Byte-Adresse 3 schreiben, dann muss die CPU daraus unter Umständen eben 
zwei Speicherzugriffe machen.

Es gibt auch 32Bit-CPUs, bei denen das Speicherinterface schmäler oder 
breiter als 32Bit ist. Beim 386sx hat es nur 16Bit, beim Pentium dagegen 
64Bit.

bye
  Markus
Gast #502942
Lesenswert?

Danke erstmal euch allen.
Mein eigentliches Problem ist, dass ich auf einen RAM Baustein (16-Bit) 
am ISA-Bus zugreifen möchte. Mit dem folgenden kleinen Programm versuch 
ich den RAM auszulesen. Leider erhalte ich nicht alle im RAM enthaltenen 
Werte.

#define BASIS 0xc8000
main()
  {
    int i;
    short mem[32];

    int fd = open("/dev/mem", O_RDWR);

    short *virtbase = mmap(0, 1024, PROT_READ | PROT_WRITE,
      MAP_SHARED, fd, BASIS);

    for (i=0; i < 8; i++){
      mem[i] = virtbase[i];
      //printf("virtbase: %x\n", virtbase[i]);
      }

    for (i=0; i < 8; i++)
      printf("mem: %x\n", mem[i]);
  }

Ergebnis:
mem: 1201
mem: 1403
mem: 1605
mem: 1807

Im RAM entahlten:
 0x1101;
 0x1202;
 0x1303;
 0x1404;
 0x1505;
 0x1606;
 0x1707;
 0x1808;

Wenn ich virtbase und mem als char definiere und das printf nicht 
auskommentiere erhalte ich folgendes Ergebnis:
virtbase: 1
virtbase: 12
virtbase: 3
virtbase: 14
virtbase: 5
virtbase: 16
virtbase: 7
virtbase: 8
mem: 1
mem: 2
mem: 3
mem: 4
mem: 5
mem: 6
mem: 7
mem: 8

Hat jemand eine Idee wie ich richtig an die Daten komme?
Danke!
Persönliche Seite #502971
Lesenswert?

Deine ISA-Karte ist nicht in Ordnung. Anscheinend ist sie nicht in der 
Lage, korrekte 8-Bit-Speicherzugriffe durchzuführen. Das Problem liegt 
vermutlich irgendwo in der Gegend der Erzeugung des Signales /MEMCS16.

Woher weißt Du, was im RAM enthalten sein soll?

Bist Du Dir sicher, daß

    short *virtbase = mmap(0, 1024, PROT_READ | PROT_WRITE,

etc. den korrekten Adressbereich der ISA-Karte angibt? RAM auf Adresse 
0?!
Gast #503296
Lesenswert?

Das /MEMCS16 Signal wir erzeugt, allerdings etwas später als eigentlich 
nötig. Da ich aber gelesen habe, dass wenn das /MEMCS16 etwas später 
also wärend des 8-Bitlesevorgangs erzeugt wird, wird ein weiterer 
Lesevorgang im selben Zyklus durchgeführt. Dies hab ich auch mit Hilfe 
eines Qszis nachgeprüft. Kann aber natürlich nicht außschließen, dass 
dies Probleme bereitet. Wie kann ich eventuell beweisen, dass es sich um 
ein Probleme bei der Karte handelt?

Ich weiß was in dem RAM enthalten ist, da es ein V-RAM ist, in den ich 
mit einem PIC ( leider kein Atmel (hat Vor- und Nachteile)) Werte 
hineinschreibe.

Ich bin mir inzwischen bei garnichts mehr sicher :-).

#define BASIS 0xC8000
short *virtbase = mmap(0, 1024, PROT_READ | PROT_WRITE,
      MAP_SHARED, fd, BASIS);

void  *  mmap(void *start, size_t length, int prot , int flags, int fd,
       off_t offset);

Die Basisadresse des RAMS ist bei 0xC8000. Die Endadresse ist 0xC83FF.
Wenn ich den Befehl richtig verstanden hab, dann wird der Seicherbereich 
ab offset nach start abgebildet. Lieg ich da ganz falsch???
Persönliche Seite #503325
Lesenswert?

Ok, das mit der Adresse könnte funktionieren. Wenn das Motherboard an 
der betreffenden Adresse nicht versehentlich RAM oder ein anderes ROM 
einblendet - hast Du mal unter DOS* mit einem Debugger nachgesehen?


*) damit meine ich NICHT die Windows-Eingabeaufforderung, sondern MS-DOS 
als "Betriebssystem". Also kein Windows, auch kein Windows 95 oder 3.11.
Persönliche Seite #503404
Lesenswert?

Bartli wrote:
>> Du kannst auf den meisten 32Bit-CPUs auch einen 32bit-Wert an die Byte-Adresse 
3 schreiben
>
> Da hätt ich jetzt gesagt, dass man das bei den meisten Architekturen
> genau nicht kann...

Welche 32Bit-Architekturen können das denn überhaupt? Mir fällt da auf 
Anhieb nur eine ein (die wohlbekannte aus Santa Klara, Kalifornien) und 
selbst dort sollte man solche Aktionen der Performance wegen lieber 
bleiben lassen.

Matthias
#503586
Lesenswert?

Matthias Weißer wrote:
> Bartli wrote:
>>> Du kannst auf den meisten 32Bit-CPUs auch einen 32bit-Wert an die Byte-Adresse 
3 schreiben
>>
>> Da hätt ich jetzt gesagt, dass man das bei den meisten Architekturen
>> genau nicht kann...

Ich geb' zu, das war eher so ein Gefühl, ich habe nicht wirklich eine 
Übersicht über die CPUs, die das können.

> Welche 32Bit-Architekturen können das denn überhaupt? Mir fällt da auf
> Anhieb nur eine ein (die wohlbekannte aus Santa Klara, Kalifornien) und

z.B. PPC:
"Although the best performance results from the use of aligned accesses, 
the PowerPC architecture is unusual among RISC architectures in that it 
permits misaligned data accesses."

und ARM ab Architektur ARMv6 (ARM11)

> selbst dort sollte man solche Aktionen der Performance wegen lieber
> bleiben lassen.

Das ist klar, aber ich wollte nur darauf hinweisen, dass Adressen im 
Programm und der Adressbus zweierlei sind.

Markus
Persönliche Seite #503590
Lesenswert?

Markus Kaufmann wrote:
> Matthias Weißer wrote:
>> Welche 32Bit-Architekturen können das denn überhaupt? Mir fällt da auf
>> Anhieb nur eine ein (die wohlbekannte aus Santa Klara, Kalifornien) und
>
> und ARM ab Architektur ARMv6 (ARM11)

Die haben das echt eingebaut? Naja evtl. gibt es tatsächlich ARM-Systeme 
die etwas knapp an Speicher sind.

>> selbst dort sollte man solche Aktionen der Performance wegen lieber
>> bleiben lassen.
>
> Das ist klar, aber ich wollte nur darauf hinweisen, dass Adressen im
> Programm und der Adressbus zweierlei sind.

Genau. Um den eigentlichen Adressbus kümmert sich ein Hardwerker :-)

Matthias
#503601
Lesenswert?

Matthias Weißer wrote:
> Markus Kaufmann wrote:
>> Matthias Weißer wrote:
>>> Welche 32Bit-Architekturen können das denn überhaupt? Mir fällt da auf
>>> Anhieb nur eine ein (die wohlbekannte aus Santa Klara, Kalifornien) und
>>
>> und ARM ab Architektur ARMv6 (ARM11)
>
> Die haben das echt eingebaut?

Ich hatte damit noch nichts zu tun, aber der englische Wikipedia-Artikel 
zur ARM-Architektur sagt:
"No support for misaligned memory accesses (now supported in ARMv6 
cores)"

> Naja evtl. gibt es tatsächlich ARM-Systeme
> die etwas knapp an Speicher sind.

Kann ich mir nicht wirklich vorstellen. Verbaut sind diese CPUs 
angeblich in Nokia N93, Zune und Nokia N800.

Ich verstehe aber nicht, wieso das nicht mehr CPUs haben. Transistoren 
sind heutzutage ja nicht mehr so teuer wie früher und das externe RAM 
ist bei großen CPUs ja eh weit weg (von der Logik her) und der Aufwand, 
den sonst der Compiler treiben muss macht das System ja auch nicht 
schneller.

Markus
Gast #503835
Lesenswert?

Verbieg dir doch auf nem System welches nur auf ausgerichtete Adressen 
zugreifen kann z.B. einen int* auf eine ungerade Adresse und lies davon 
- der Compiler wird dir das kompilieren, aber funktionieren wirds nicht.

=> Null Aufwand auf der Compilerseite.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren