Pointer ist 3 Byte große?

OP #1474609
Lesenswert?

Hallo!

Ich habe ein merkwürdiges Problem: Ich möchte gerne die Adresse eines 
Pointers (vom Pointer selbst) in einzelnen Bytes Speichern. Da das nicht 
auf anhieb funktioniert hat (das Zerlegen des Pointers), habe ich mal 
folgendes ausprobiert:
1
sizeof(char*);

Das liefert mir zu meinem Erstaunen den Wert 3!! Warum das denn? Ich 
nutze den An2131 von Cypress mit einem 8051-Kern. Das müsste doch 
eigentlich 2 zurückliefern, oder?

Viele Grüße,
Stefan
#1474631
Lesenswert?

Für Maschinen mit getrennten Adressräumen existieren Compiler, die mit 
Pointern alle Adressen ansprechen können. Realisiert wird das, indem zur 
Adresse noch eine Adressraumkennung hinzugefügt und der Zugriff per 
Laufzeitfunktion abgewickelt wird. Das könnte hier der Fall sein. 
Möglicherweise ist dann per Option wählbar, ob das für alle Pointer 
gilt, oder nur für solcherart gekennzeichnete.
Gast #1474644
Lesenswert?

Insbesondere beim 8051 ist das erforderlich, da es 
Adressüberschneidungen gibt. Der Pointer muss also ein Angabe enthalten, 
für welchen Speicher er gilt (data, idata, xdata, code), zumindest gilt 
das für den generic-Pointer.
Das 1.Byte des pointers stellt also den Typ dar, danach kommen 2 
Adress-Bytes. Kann allerdings bei anderen Compilern auch anders sein:-).

Wenn du den Speichertyp schon bei Deklaration angibst, hat er auch nur 2 
Byte, kann dann allerdings wirklich nur für diesen Speichertyp verwendet 
werden.
Gast #1474828
Lesenswert?

> Das müsste doch eigentlich 2 zurückliefern, oder ?

Nein.
Auch beim C166 sind's 3, bei manchen Mainframes auch 6.

Vermutlich ist der Cypress-Kompiler so flexibel,
dass er Zeiger in Code und Zeichen in (externes) RAM
unterschieden kann und braucht dafür 1 bit mehr als 16.

Manchmal kann man daran mit Compileroptionen drehen,
aber man sollte sich über die Konseqeunzen im klaren
sein, wenn Pointer nicht mehr unterschiedbar sind.
#1474845
Lesenswert?

Jup ein Pointer mit Typisierung, geht für alles, erzeugt mehr Code und 
ist langsamer.
schau mal ins Manual deines Compilers, da sollte es drin stehen.

Ich kenns von sdcc:
generische pointer, wie in deinem fall haben 3 byte.
spezialisierte pointer, z.B. für xram haben nur 2 byte.
theoretisch könnte ein pointer für den data-,idata- oder pdata- bereich 
auch nur 8bit haben, ob das der sdcc kann, weiß ich allerdings gerade 
nicht.

Wie auch immer, wenn du spezielle pointer verwenden willst, muss du dir 
gedanken um dein memory-model machen und dein code muss auf das verdauen 
spezieller pointer ausgelegt sein.
OP #1475300
Lesenswert?

Hey!
Danke erstmal für die vielen Antworten, jetzt ist mir die Sache auch 
klar geworden :D
Was ich aber komisch finde: Kann es sein, dass der 8051 eine Adresse 
"falsch herum" abspeichert? Wenn var0 an Adresse 0D60 sitzt und ich 
folgendes mache
1
var5 = (unsigned char) (&var0);
2
var6 = (unsigned char) (((int)(&var0))>>8);
3
var7 = (unsigned char) (((int)(&var0))>>16);
liefert mir das als Resultat

var5 = 60
var6 = 0D
var7 = 0

Gut, hier fällt mir schonmal auf, dass die 1, die dem Pointer auf Grund 
der Lage im XDATA-Bereich haben müsste, nicht enthalten ist...

Mache ich nun folgendes:
1
xdata long test _at_ 0x0D70;
2
test = &var0;
und lese nacheinander die Speicherzellen 0x0D70, 0x0D71, 0x0D72 aus (vom 
PC), so liefert mir das für
0x0D70: 0
0x0D71: 01
0x0D72: 0D
0x0D73: 60

Kann mir das jemand erläutern?

Viele Grüße,
Stefan
#1475346
Lesenswert?

Andreas R. schrieb:
> Wie auch immer, wenn du spezielle pointer verwenden willst, muss du dir
> gedanken um dein memory-model machen

Nö, das Memory Model gibt nur an, wo default Variablen abgelegt werden.

Deshalb sollte man das Large-Modell nur dann nehmen, wenn man wirklich 
triftige Gründe dafür hat. Default Variablen werden dann nämlich sehr 
langsam und erzeugen sehr viel Code.

In jedem Memory-Model kann man alle Memory-Specifier verwenden.
Pointer ohne Specifier sind immer 3 Byte groß (generic Pointer).


Peter
OP #1475390
Lesenswert?

A. K. schrieb:
> Stefan S. schrieb:
>
>> var7 = (unsigned char) (((int)(&var0))>>16);
>
> Wird immer 0 sein, weil "int" nur 16 Bits hat. Besser:
>
> var7 = (unsigned char) (((long)(&var0))>>16);

Okay, das macht Sinn ;-) habs mal mit "long" statt "int" versucht, jetzt 
ist die 1 wieder da!

Nach dem, was ich im Netz gefunden habe, scheint der AN2131 mit dem 
8051-Kern also nach Big-Endian-Format sortiert...

Danke!

Viele Grüße,
Stefan
#1475407
Lesenswert?

Gast schrieb:

> Intel µCs haben immer little-endian.

Das ist hier nicht relevant, da der 8051 alle Pointer jenseits des 256 
Byte Primär-RAMs über DPTR nutzt. Daher kann der Programmierer das 
halten wie er will.

In diesem Fall könnte eine Rolle spielen, dass die Laufzeitfunktionen 
zuallererst auf das Tag-Byte zugreifen müssen, dies also sinnvollerweise 
an der ersten Stelle steht.

> Motorola, Renesas (H8) big-endian und SH sind meist umschaltbar.
> Ist das nicht schön? :-)

Noch schöner war NS32000. Big-endian bei Konstanten im Code und 
little-endian sonst. DEC hatte auch welche verbrochen, bei denen die 
Bytereihenfolge im Wort und die Wortreihenfolge im Doppelwort 
unterschiedlich war
Gast #1475475
Lesenswert?

Der AN2131 ist nicht zwingend in einem festen Format sortiert. Die 
endianess der Variablen im Speicher bestimmt der Compiler.

Keil macht für den 8051 big endian.
sdcc little endian.

Genauso machen das die Hardwaredesigner mit den Peripheriemodulen,
dort können 16bit Register wiederum in beliebiger Reihefolge liegen.
hab mal das Datenblatt des AN2131 überflogen(den ich noch die verwendet 
habe).
Im USB-Teil sind einige 16bit register etc big-endian, andere wiederum 
little-endian.
Solange du auf die Register immer schön mittels der Namen der 
Einzelbytes zugreifst und sie von Hand "zusammenshiftest" ist alles in 
Butter.
Gast #1475680
Lesenswert?

>Die endianess der Variablen im Speicher bestimmt der Compiler.

Nee, nee. Bei 8-Bittern kann er das machen, aber sobald ein 16- oder 
32-Bitter eine int oder long-Variable speichert, legt die CPU (oder 
sogar das Businterface) die Anordnung fest.
#1475687
Lesenswert?

Gast schrieb:

> Nee, nee. Bei 8-Bittern kann er das machen, aber sobald ein 16- oder
> 32-Bitter eine int oder long-Variable speichert, legt die CPU (oder
> sogar das Businterface) die Anordnung fest.

Klar doch, aber hier geht es eben um 8051, da legt die Maschine nichts 
fest und der Compiler hat die Wahl.

Auch bei vielen 8-Bit Prozessoren wird das durch 16-Bit Adressen im 
Speicher ebenfalls von der Maschine fest- oder nahegelegt, aber eben 
nicht bei 8051.

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