2017-04-10 15 views
2

Also muss ich ein Assembly-Programm schreiben, das extern C-Funktion aufrufen würde. Also schrieb ich einfach pow Funktion, kompilierte ich mein Assembly-Programm mit diesem C-Code. Funktioniert alles. Aber wie ich aus -S Befehl von gcc sah, macht der Compiler einen Platz für lokale Variablen. Ich dachte, es so sein würde:Platz für lokale Variablen in Assembly machen

int func(int number) 
{ 
    int a = 10; 
    int b = 5; 
    int c = 0; 
} 

Wir haben drei lokale Variablen, so dass der Compiler würde subl $12, %esp. Aber es geht für subl $16, %esp. Selbst wenn ich hier nur eine Zahl belassen würde, würde sie trotzdem um 16 dekrementieren. Jetzt habe ich meinen Code:

main.s:

.section .data 
.XD: 
    msg: .ascii "%d\n" 
    msg_len = . - msg 

.text 
.globl _pow 
.globl main 

main: 
    pushl %ebp 
    movl %esp, %ebp 
    movl $5, %eax #like int a = 5; 
    pushl %eax 
    call _pow #_pow(a); 
    movl %eax, -8(%ebp) 
    pushl -8(%ebp) 
    pushl $.XD 
    call printf #printf("%d\n", _pow(a)); 
    movl $0, %eax 
    leave 
    ret 

func.c:

int _pow(int number) 
{ 
    return number * number; 
} 

Es funktioniert wie erwartet, ./main druckt 25. Aber jetzt, ich habe keine subl irgendetwas von %esp. Ich meine, ich kann diese Zeile hinzufügen, aber es ändert nichts. Ich habe im Internet gesucht und herausgefunden, dass mein Code vielleicht nur zufällig funktioniert und ich sollte generell %esp dekrementieren. Also meine Frage hier ist: Um welchen Wert sollte ich %esp in main dekrementieren? Sollte es 12 oder vielleicht 16 sein?

+4

Die Verwendung von '16' ist sehr wahrscheinlich, dass der Stapel 16-Byte-ausgerichtet zu halten. – unwind

+0

Ich denke, Sie haben Recht, aber sollte ich es dann immer 16-Byte ausgerichtet machen, oder sollte ich bestimmte Werte "unterbinden"? – Frynio

+1

Die Anforderung wird wahrscheinlich in der ABI-Dokumentation (Application Binary Interface) der Plattform angegeben. Da es sich um eine Spezifikation handelt, sollten Sie sie befolgen, um mit anderem Code interagieren zu können. – unwind

Antwort

0

Da Sie eine 32-Bit-C-Funktion aufrufen, müssen Sie die C calling convention folgen. Anders als bei 64-Bit-Systemen gibt es keine explizite Reihenfolge zum Ausrichten des Stapels. Ich konnte keine Aussage finden, wenn solch eine Ausrichtung stattfinden sollte. Der Stapel könnte nach dem Drücken der Parameter "falsch ausgerichtet" sein.

Wenn Sie den Stapel ausrichten Sie einfach und -16, nachdem Sie es gespeichert (movl %esp, %ebp):

andl $-16, %esp    ; Align 16 
+0

Dies ist genau das, was 'gcc' tut, wenn C-Code kompiliert wird. Hmm, aber sollte ich dann etwas von esp "unterdrücken", um Platz für lokale Variablen zu schaffen? – Frynio

+0

Zuerst "subl" für lokale Variablen (falls erforderlich) und dann 'andl' für die Ausrichtung.Allerdings bin ich ziemlich sicher, dass Sie keine 16-Byte-Ausrichtung für 32-Bit-C benötigen. – rkhb

+0

Okay, ich weiß, dass ich es nicht brauche. Aber 'gcc'" subles "einige Werte, aber dann wird es nicht mit' addl'iing ausgerichtet. Ich meine es tut - mit 'verlassen' Anweisung. Aber die Frage ist hier - muss ich etwas von '% esp'' unterdrücken? – Frynio