2016-06-26 10 views
2

weise mehr über Assemblersprache/Computerarchitektur Lernen, schrieb ich die folgende C-Code:Was passiert mit dem Stapelzeiger in diesem einfachen (zerlegten) C-Programm?

int my_caller() { 
    int a = my_callee(0xbaba); 
    return a; 
} 

int my_callee(int a) { 
    return a; 
} 

Diese Disassembliert (auf meiner Maschine, mit einigen zusätzlichen Kommentaren) auf die folgenden:

; my_caller function 
push ebp 
mov ebp,esp 
sub esp,byte +0x18 
sub esp,byte +0xc 
push dword 0xbaba 
call dword 0x1e 
add esp,byte +0x10 
mov [ebp-0xc],eax 
mov eax,[ebp-0xc] 
leave 
ret 

; my_callee function 
push ebp 
mov ebp,esp 
mov eax,[ebp+0x8] 
pop ebp 
ret 

in Bezug auf die Behandlung von esp in my_caller:

  1. Warum tun wir sub esp von 0x18 und dann 0xc; Warum nicht nur eine einzige Untereinheit von 0x24?
  2. Nach der Rückkehr von my_callee, was ist der Punkt add esp,byte 0x10? Die leave Anweisung wird dies sowieso mit dem impliziten mov esp,ebp annullieren.

Danke.

+5

Sie haben vergessen, die Optimierung zu aktivieren. – Jester

+1

Compiler generieren * guten * Code, aber nicht unbedingt den * besten * Code, mit oder ohne Optimierung. Zum Beispiel könnten zwei aufeinanderfolgende "sub esp" -Befehle erzeugt werden, weil sie aus zwei verschiedenen Gründen erzeugt wurden. Der Code, den Sie sehen, verwaltet den "Stack-Frame" und die Parameter und lokalen Variablen. "Jede Sprache ist anders", wie es das macht. Dies ist ein Grund, warum es schwierig sein kann, Bibliotheken aufzurufen oder Sprachen in einem Projekt zu mischen. –

+0

hängt vom Compiler (und seiner Version) und den Befehlszeilenoptionen für Starter ab. Wenn gcc zum Beispiel sinnvoll ist, kann es sinnvoll sein, den Code zu betrachten. es kann eine Anpassung an einem Ort für eine Sache und eine andere aus einem anderen Grund geben, und jene, die irgendwo der Gucklochoptimierer nicht erreichen kann. Oder Sie verwenden keinen Compiler mit irgendeiner Optimierung, sogar Guckloch .... –

Antwort

2

Sie haben dem Compiler gesagt, dass er schnell kompilieren soll, um keinen guten Code zu machen und Code zu erstellen, der für einen Debugger wie gdb einfach ist. In -O0 Modus, gcc nicht viel zwischen verschiedenen Teilen der gleichen Funktion optimiert, daher die add esp, 0x10 den Stapel nach dem Anruf Pop, und dann leave getrennt.

-O0 ist schrecklich laut (voll von Geschäften/Nachladungen), so dass es saugt, als Mensch zu lesen.

Sie haben mehr Glück beim Betrachten von Funktionen, die ein paar int Args nehmen und eine int zurückgeben. Sie können __attribute__((noinline)) auf Funktionen verwenden, um sie vom Inlining zu stoppen.

Schauen Sie sich zum Beispiel eine einfache Funktion auf dem Godbolt compiler explorer an. Siehe auch das Tag-Wiki.