IA32 und Speichermodelle (und Speicherausrichtung)



  • Folgendes angenommen auf einem IA32 Rechner:

    Es wird ein Word a , Dword b, byte c und Word d belegt. Nach IA32 ist ein Word 16bit, ein DWord 32bit, ein byte 8 bit. Richtig? Dabei haben wir folgendes Speichermodell:

    http://fs5.directupload.net/images/151103/dxs4zq48.png

    Wie wird die Speicherreservierung wahrscheinlich aussehen? Kann mir das einer erklären?



  • Was für eine Speicherbelegung? Stack ist üblicherweise 4-byte aligned. Da würde jeder deiner Werte 4 Byte belegen. Structs in C und C++ sind hingegen self-aligned. Das heißt die Werte liegen an Adressen die durch ihre Länge teilbar sind und entsprechend wäre z.B. zwischen deinem a und b ein Word padding.



  • Generell musst du neben den Speichereinheiten, die du ja schon richtig aufgezählt hast nur wissen, dass:
    []IA32 ein "little-endian" Modell ist, d.h im Speicher werden zunächst die leichtgewichtigen Bytes und anschließend dir mehr ins Gewicht fallenden Bytes angeordnet.
    [
    ]Die Adressen "wachsen" damit in entgegengesetzter Richtung.

    Ich versuch das mal ganz simpel darzustellen, der Wert sei 0x24354320 (dez.: 607470368)

    Adresse Hexadezimalwert

    0x1000 0x20
    0x1001 0x43
    0x1002 0x35
    0x1004 0x24

    Verstehen kann man das folgendermaßen: Der Hexadezimalwert 0x24354320 ist ein DWORD, umfasst also 4 Bytes. Das erkennt man relativ einfach, wenn sich für jedes Zahlenpaar ein Byte denkt (0x20 => 1 Byte, 0x43 => 1 Byte...). Die Umrechnung zeigt, warum 0x24 mehr ins gewicht fällt als 0x20:

    0x24354320 =>
    0*16^0 + 2*16^1
    + 3*16^2 + 4*16^3
    + 5*16^4 + 3*16^5
    + 4*16^6 + 2*16^7

    Stell dir das ruhig wie ein Datum vor. Wir beginnen mit dem Tag, dann kommt der mehr ins Gewicht fallende Monat und dann das Jahr (gut, Ausnahme wenn wir's Montag haben kann auch der Monat und das Jahr einpacken).



  • D.h. ich ordne dann die Zahl einfach von hinten her im Speicher an?

    Folgender C Code:

    long int i = 1; // Bei IA32 4 byte
    char c = 'x'; // 1 byte
    short int n = 10; // 2 byte
    short int m =11; // 2 byte
    float f = 0.0; // 4 byte
    

    Wie werden die Deklaration wahrscheinlich im Speicher abgebildet? Dabei ist es am sinnvollsten Hexziffern zu nutzen, oder?

    Wie weiß ich, wie viele Stellen dazwischen frei sein müssen?



  • @Tobiking2

    Tobiking2 schrieb:

    Stack ist üblicherweise 4-byte aligned. Da würde jeder deiner Werte 4 Byte belegen.

    Kann man so nicht sagen, kann der Compiler machen wie er mag.

    Tobiking2 schrieb:

    Structs in C und C++ sind hingegen self-aligned. Das heißt die Werte liegen an Adressen die durch ihre Länge teilbar sind und entsprechend wäre z.B. zwischen deinem a und b ein Word padding.

    Kann man so nicht sagen, kann der Compiler machen wie er mag.

    @CrispyTurtleAlligator

    CrispyTurtleAlligator schrieb:

    Wie werden die Deklaration wahrscheinlich im Speicher abgebildet?

    Kann man so nicht sagen, kann der Compiler machen wie er mag.

    CrispyTurtleAlligator schrieb:

    Dabei ist es am sinnvollsten Hexziffern zu nutzen, oder?

    Wie weiß ich, wie viele Stellen dazwischen frei sein müssen?

    Was willst du denn eigentlich wissen bzw. erreichen?



  • hustbaer schrieb:

    Kann man so nicht sagen, kann der Compiler machen wie er mag.

    😃



  • hustbaer schrieb:

    @Tobiking2

    Tobiking2 schrieb:

    Stack ist üblicherweise 4-byte aligned. Da würde jeder deiner Werte 4 Byte belegen.

    Kann man so nicht sagen, kann der Compiler machen wie er mag.

    Tobiking2 schrieb:

    Structs in C und C++ sind hingegen self-aligned. Das heißt die Werte liegen an Adressen die durch ihre Länge teilbar sind und entsprechend wäre z.B. zwischen deinem a und b ein Word padding.

    Kann man so nicht sagen, kann der Compiler machen wie er mag.

    @CrispyTurtleAlligator

    CrispyTurtleAlligator schrieb:

    Wie werden die Deklaration wahrscheinlich im Speicher abgebildet?

    Kann man so nicht sagen, kann der Compiler machen wie er mag.

    CrispyTurtleAlligator schrieb:

    Dabei ist es am sinnvollsten Hexziffern zu nutzen, oder?

    Wie weiß ich, wie viele Stellen dazwischen frei sein müssen?

    Was willst du denn eigentlich wissen bzw. erreichen?

    Mein Professor in Rechnerarchitektur will das so haben! Die Frage war nicht, ob es sicher so ist, sondern wie es bei IA32 wahrscheinlich so ist. Tipps? 🙂



  • In nem struct gilt wahrscheinlich:
    Anordnung im Speicher in genau der Reihenfolge wie die Variablen im struct stehen.

    Dazwischen Padding wie hier beschrieben:
    https://msdn.microsoft.com/en-us/library/2e70t5y1.aspx?f=255&MSPPError=-2147217396

    Sollte es sich wirklich um lokale Variablen handeln, dann gilt leider weiterhin: Kann man so nicht sagen, kann der Compiler machen wie er mag. Und macht er auch wie er mag!
    In vielen Programmen stehen da z.B. viele Variablen überhaupt gar nicht im Speicher, weil sie einfach in Registern gehalten werden. Und so lange man nicht die Adresse der Variable irgendwohin "entweichen" lässt wo der Compiler nix mehr sieht (=kein Inlining mehr machen kann) kann es sein dass sogar Variablen die - weil zu wenig Register da sind - im Speicher abgelegt werden keine fixe Adresse haben. Sondern mal da und mal dort gespeichert werden.
    Die Frage dabei ist nicht wie wahrscheinlich sich das so verhält, das ist so.
    Google mal nach den Begriffen "register allocation" und "static single assignment form".

    Kein aktueller Compiler wird in Builds "mit Optimierungen" (=ganz normale Release Builds) auch nur irgendwelchen Code für die von dir gezeigten Deklarationen erzeugen oder Speicher reservieren oder sonstwas. So lange die Variablen nicht verwendet werden compiliert das ganze zu genau Null Maschinenbefehlen.

    Und selbst wenn man die Variablen verwendet gilt in Builds "mit Optimierungen" ... naja gut das hab ich ja schon beschrieben.

    In Debug Builds wird es vermutlich mit jedem Compiler ein mehr oder weniger einfach zu verstehendes Muster geben.
    Nur wird das anders aussehen, je nachdem welchen Compiler du verwendest.
    Beispiel:

    int main()
    {
    	long int i = 11; // Bei IA32 4 byte
    	char c = 22; // 1 byte
    	short int n = 33; // 2 byte
    	short int m = 44; // 2 byte
    	float f = 0.0; // 4 byte
    }
    
    ==>
    
    CLang 3.0:
    	pxor	%xmm0, %xmm0
    	movl	$0, -4(%rsp)
    	movq	$11, -16(%rsp)                 # i
    	movb	$22, -17(%rsp)                 # c
    	movw	$33, -20(%rsp)                 # n
    	movw	$44, -22(%rsp)                 # m
    	movss	%xmm0, -28(%rsp)               # f
    
    CLang 3.5.1:
    	xorps	%xmm0, %xmm0
    	movq	$11, -8(%rbp)                  # i
    	movb	$22, -9(%rbp)                  # c
    	movw	$33, -12(%rbp)                 # n
    	movw	$44, -14(%rbp)                 # m
    	movss	%xmm0, -20(%rbp)               # f
    
    GCC 5.2.0:
    	movq	$11, -8(%rbp)                  # i
    	movb	$22, -9(%rbp)                  # c
    	movw	$33, -12(%rbp)                 # n
    	movw	$44, -14(%rbp)                 # m
    	pxor	%xmm0, %xmm0
    	movss	%xmm0, -20(%rbp)               # f
    
    GCC 4.9.2:
    	movq	$11, -8(%rbp)                  # i
    	movb	$22, -17(%rbp)                 # c
    	movw	$33, -16(%rbp)                 # n
    	movw	$44, -14(%rbp)                 # m
    	movl	.LC0(%rip), %eax
    	movl	%eax, -12(%rbp)                # f
    
    icc 13.0.1:
    	movq      $11, -16(%rbp)               # i
    	movb      $22, -32(%rbp)               # c
    	movw      $33, -30(%rbp)               # n
    	movw      $44, -28(%rbp)               # m
    	pxor      %xmm0, %xmm0
    	movss     %xmm0, -24(%rbp)             # f
    

    Kannst dich auch gerne selbst damit rumspielen, geht ja dank gcc.godbolt.org sehr einfach: https://goo.gl/UGAh0Z

    3 verschiedene Compiler, 4 verschiedene Layouts.
    Du darfst dir jetzt selbst aussuchen was das "wahrscheinliche" Layout ist.

    =>

    Die Frage ist einfach nur dumm. Wenn dein Professor meint die Frage sei schlau hilft dir das natürlich nicht viel.



  • Danke für die ausführliche Antwort! Kannst du mir das mit dem Padding (in welchem Falle eines kommt, in welchem nicht) mit eigenen Worten erklären? Der Link hat mir nicht so die Erleuchtung gebracht. 🙄



  • Stichwort Aufrunden?



  • hustbaer schrieb:

    Stichwort Aufrunden?

    Hat sich geklärt. Falls mal jemand eine ähnliche Frage hat: Speicherausrichtung ist das Stichwort. 🙂



  • CrispyTurtleAlligator schrieb:

    Speicherausrichtung ist das Stichwort. 🙂

    Das wusstest du doch schon als du den Thread "IA32 und Speichermodelle (und Speicherausrichtung)" nanntest, oder?



  • Im Englischen sagt man dazu auch "alignment".
    Ein Begriff der in der MSDN Seite zu #pragma pack durchaus 1-2 mal erwähnt wird.


Log in to reply