2017-03-21 3 views
-2

Englisch ist es nicht meine erste Sprache, also wenn ich falsch einige Wörter falsch buchstabiere. Ich habe einige Probleme mit dem Stack, alle Codes, die ich hier setzen werde, funktionieren perfekt.kann mir jemand den Stack dieses Codes erklären?

Dieser Code zum Beispiel ist einfach und ich verstehe den Stapel davon.

 

    .globl f 
    f: 

    push %ebx 
    movl 8(%esp), %eax 
    movl 12(%esp), %ebx 

    addl %ebx, %eax 

    ret 

STACK

 
    ------- 
    VAR Y --> ESP + 12 
    ------- 
    VAR X --> ESP + 8 
    ------- 
    RET --> RETURN 
    ------- 
    %EBX --> %ESP 
    ------- 

Aber mit diesem Code Ich habe einige t

 

    .code32 

    .globl f 

    f: 

     pushl %ebx 

     movl 8(%esp), %ebx 

     subl $8, %esp # Creo posto nella stack per i parametri 

     movl $1, (%esp) 

     movl $2, 4(%esp) 

     call a 

     addl %ebx, %eax 

     addl $8, %esp #Tolgo posto nella stack 

     popl %ebx 

     ret 


Der Code funktioniert perfekt, aber ich habe viele Fragen darüber ?. Wo ist jetzt% ebx und ret auf Stack?

Code of asm transalted in c:

 

    int f(int x){ 

    return x + g(y,z); 

    } 

Und dies ist der Stapel, der i

STACK

 

    -------- 
    8(%esp) --> x parameter of function f 
    -------- 
    4(%esp) --> z parameter of function g 
    -------- 
    (%esp) --> y parameter of funcion g 
    -------- 

So ist die Frage jetzt gemacht haben, ist, wo sind% ebx und auf diesem Stapel jetzt ret?

Antwort

0

Der erste Code wird auf den alten ebx Wert (wahrscheinlich keine gültige Adresse), nicht auf die ursprüngliche Absenderadresse, es fehlt pop ebx vor ret.

Im zweiten rufen die Erinnerung an ss:esp Adresse, bevor call a Anweisung enthält:

dword 1      +0 (current esp) 
dword 2      +4 
dword old_ebx_value   +8 
dword return_address_from_f +12 
dword x      +16 
... older stack content ... 

Ihre "esp + x" Notation funktioniert nicht, da der esp dynamisch ändert, wenn Sie so wollen Um einen solchen Stack zu beschreiben, müssen Sie sagen, an welcher Position im Code (welchen Wert von esp) Sie verwenden. Ie. am Eingang von f wird die mov eax,[esp+4] wird geladen das "x", aber nur eine Anweisung später nach push ebx das gleiche wird erreicht durch mov eax,[esp+8] (Intel-Syntax, konvertieren zu diesem "Maschine" Gas/& t Syntax selbst, ich bin Mensch).

Aber selbst wenn Sie es als Speicherwerte darstellen, ändert es sich dynamisch mit jedem push oder schreibt in den Speicher, also müssen Sie noch angeben, an welchem ​​Punkt der Ausführung Sie den Stapel beschreiben (wie ich vorher getan habe) von call a, denn nach call aaddl %ebx, %eax die Adresse der Anweisung gibt es geschrieben vor diesem Wert 1 und Code bei a nicht in Frage gezeigt.

Wie dem auch sei, die alte ebx und Adresse zurück sind im Speicher an der gleichen Stelle die ganze Zeit (es sei denn a überschreibt sie, es ist nicht der Inhalt, der sich bewegt. Es ist der Zeiger esp das wird von push/pop/add/sub angepasst. (Der Speicherinhalt bleibt auch nach pop es, es ist einfach nicht sicher anzunehmen, wie lange anderer Code benötigt wird, um ihn zu überschreiben. Falls die SW-Interrupt-Handler den App-Stack verwenden, kann dieser überschrieben werden Zeit, obwohl in der x86 32b-Modus in der Regel die App hat einen eigenen Stapel, so dass diese Werte werden wahrscheinlich dort bleiben, bis Sie sie durch nächste push oder call oder auf andere Weise überschreiben.

schließlich nur jene Dinge machen zu kompilieren und sie in Debugger ausführen, Speicheransicht zu ss:esp-32 an dem Anfang, und beobachten, wie der Speicher durch Anweisungen wie call oder push geschrieben wird, und wie esp ändert Zeigen Sie auf die "Spitze des Stapels". Es ist normalerweise viel einfacher, es im Debugger "zu beobachten", als Text wie meine Antwort zu lesen.

Verwandte Themen