2017-05-24 2 views
1

Der Titel ist eigentlich mein zweites Problem. 2 Probleme traten auf, als ich die 2. Auflage der CSAPP, Kapitel 3, lernte. Es gibt 2 relativ einfache Dateien. Hier ist die erste:Warum% esp wird imexplitcitly geändert?

// code.c 
    int accum = 0; 

    int sum(int x, int y) 
    { 
     int  t = x + y; 
     accum += t; 
     return t; 
    } 

Die zweite:

// main.c 
    int main() { 
     return sum(1, 3); 
    } 

ich gcc verwendet, um sie zu erstellen, nach dem Buch. Um eine 32-Bit-Programm zu erhalten, habe ich eine -m32 Option (Meins ist 64-bit Ubuntu):

$ gcc -m32 -O1 -O prog code.c main.c 

Dinge waren weit diese gut auf. Aber als ich es mit GDB zerlegte, verwirrte es mich wirklich. Ich habe das folgende Ergebnis, dass in Konflikt mit dem, was das Buch sagt:

(gdb) disas sum 
    Dump of assembler code for function sum: 
     0x080483ed <+0>: mov 0x8(%esp),%eax 
     0x080483f1 <+4>: add 0x4(%esp),%eax 
     0x080483f5 <+8>: add %eax,0x804a020 
     0x080483fb <+14>: ret  
    End of assembler dump. 
    (gdb) disas main 
    Dump of assembler code for function main: 
     0x080483fc <+0>: push %ebp 
     0x080483fd <+1>: mov %esp,%ebp 
     0x080483ff <+3>: and $0xfffffff0,%esp 
     0x08048402 <+6>: sub $0x10,%esp 
     0x08048405 <+9>: movl $0x3,0x4(%esp) 
     0x0804840d <+17>: movl $0x1,(%esp) 
     0x08048414 <+24>: call 0x80483ed <sum> 
     0x08048419 <+29>: leave 
     0x0804841a <+30>: ret  
    End of assembler dump. 

Jetzt sind hier meine Probleme:

  1. Warum ist es eine Einsparung% ebp oder esp bewegen% beim Aufruf der Funktion Summe wie das Buch beschreibt? Oder ist Summe inlined vom Compiler?
  2. Der Wert 3 & 1 wurde bereits im M [% esp + 4] & M [% esp] gespeichert. Und nach dem Aufruf der Summe gibt es keine Anweisung, die den in% esp gespeicherten Wert ändert. Aber innerhalb der Summe, die erste Anweisung ruft M [% esp + 8], die eigentlich 3 ist (Ich legte den Haltepunkt mit GDB & überprüfte den Wert), während die M [% esp + 4] den Wert 1 speichert. Woher? Später stellte ich 2 Stützpunkte:

    (gdb) break *0x08048414 
    (gdb) break sum 
    

Dann fand ich das in% esp gespeicherten Wert war anders an diesen 2 Stützpunkte:

 Breakpoint 6, 0x08048414 in main() 
    (gdb) print $esp 
    $8 = (void *) 0xffffd020 
    (gdb) continue 
    Continuing. 

    Breakpoint 5, 0x080483ed in sum() 
    (gdb) print $esp 
    $9 = (void *) 0xffffd01c 

Warum sollte dies geschehen?

+1

Was ist mit 'push',' pop', 'call',' ret'? – tkausl

+0

Es scheint seltsam, dass dieser Code erfolgreich kompiliert wurde, weil 'sum()' nicht in 'main.c' definiert ist. Ist das der eigentliche Code, den du kompiliert hast? –

+0

@LiranFunaro Ich denke mit C und schlechten Compiler-Einstellungen wird es nur warnen "undefined, ich nehme an, es gibt int zurück und nimmt tatsächlich diese Argumente" –

Antwort

1

Warum wird% ebp nicht gespeichert oder% esp verschoben, wenn die Funktion sum aufgerufen wird, wie im Buch beschrieben?

Möglicherweise haben Sie die Option aktiviert, um den Rahmenzeiger zu überspringen, höchstwahrscheinlich mit der -Ox-Compileroption. Sie können GCC zwingen, noch zu halten, mit -fno-omit-frame-pointer GCC Befehlszeilenargument:

https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-O

Aber in der Summe wird der erste Befehl ruft M [% esp + 8], das ist eigentlich 3, während das M [% esp + 4] den Wert 1 speichert. Wie kommt es?

Aufrufanweisung schiebt das EIP-Register zum Stack und verschiebt esp. Sie haben es im 32-Bit-Modus kompiliert, also beträgt der Offset 4 Byte.

Verwandte Themen