c & gcc: Stapelwachstum und -ausrichtung - für eine 64-Bit-Maschine

8

Ich habe folgendes Programm. Ich frage mich, warum es -4 auf der folgenden 64-Bit-Maschine ausgibt? Welche meiner Annahmen ist falsch gelaufen?

  

[Linux ubuntu 3.2.0-23-generische # 36-Ubuntu SMP Di Apr 10 20:39:51 UTC   2012 x86_64 x86_64 x86_64 GNU / Linux]

  1. Im obigen Computer und GCC-Compiler sollte standardmäßig b zuerst und eine Sekunde gedrückt werden. Der Stapel wächst nach unten. Also sollte b eine höhere Adresse und eine niedrigere Adresse haben. Das Ergebnis sollte positiv sein. Aber ich habe -4. Kann jemand das erklären?

  2. Die Argumente sind zwei Zeichen, die 2 Byte im Stapelrahmen belegen. Aber ich sah den Unterschied als 4, wo ich erwarte 1. Selbst wenn jemand sagt, dass es wegen der Ausrichtung ist, dann frage ich mich, ob eine Struktur mit 2 Zeichen nicht mit 4 Bytes ausgerichtet ist.

%Vor%
    
Lunar Mushrooms 16.06.2012, 02:59
quelle

3 Antworten

5

Der beste Weg, diese Fragen zu beantworten (über das Verhalten eines bestimmten Compilers auf einer bestimmten Plattform), ist der Assembler. Sie können gcc erhalten, um seinen Assembler zu entladen, indem Sie das -S -Flag übergeben (und das -fverbose-asm -Flag ist auch nett). Ausführen

%Vor%

gibt ein file.s , das ein wenig aussieht (Ich habe alle irrelevanten Bits entfernt, und die Bits in Klammern sind meine Notizen):

%Vor%

( Diese Frage erklärt nett, was [re]bp und [re]sp sind.)

Der Grund für den Unterschied ist, dass der Stack nach unten wächst: Wenn Sie also zwei Dinge auf den Stack schieben, hat der erste Push eine größere Adresse und a wird vor b geschoben.

Der Grund dafür ist -4 und nicht -1 . Der Compiler hat entschieden, dass das Ausrichten der Argumente auf 4 Byte Grenzen "besser" ist, wahrscheinlich weil eine 32 Bit / 64 Bit CPU mit 4 Byte besser ist Es behandelt einzelne Bytes.

(Wenn man sich den Assembler anschaut, sieht man auch den Effekt, den -mpreferred-stack-boundary hat: es bedeutet im Wesentlichen, dass Speicher auf dem Stack in Blöcken unterschiedlicher Größe zugewiesen wird.)

    
huon 16.06.2012, 03:40
quelle
9

Hier ist meine Vermutung:

Unter Linux in x64 gibt die Aufrufkonvention an, dass die ersten paar Parameter von register übergeben werden.

In diesem Fall werden sowohl a als auch b vom Register und nicht vom Stack übergeben. Da Sie jedoch seine Adresse verwenden, speichert der Compiler sie irgendwo auf dem Stapel , nachdem die Funktion aufgerufen wurde.
(In absteigender Reihenfolge nicht erforderlich.)

Es ist auch möglich, dass die Funktion einfach direkt inline ist.

In beiden Fällen erstellt der Compiler temporären Stapelspeicher zum Speichern der Variablen. Diese können in beliebiger Reihenfolge vorliegen und unterliegen Optimierungen. Sie können also nicht in einer bestimmten Reihenfolge sein, die Sie erwarten könnten.

    
Mysticial 16.06.2012 03:07
quelle
0

Ich denke, dass die Antwort, die Ihnen das Programm gab, korrekt ist, die Standard-Stackgrenze von GCC ist 4, Sie können -mpreferred-stack-boundary=num auf GCC-Optionen setzen, um die Stack-Boudary zu ändern, dann gibt Ihnen das Programm die andere Antwort dein Set.

    
MYMNeo 16.06.2012 03:28
quelle

Tags und Links