2013-07-13 7 views
15

Ich bin sehr neu in Assembly, und ich verstehe nicht, was es genau bedeutet, wenn Sie am Ende eines Proc, schreiben Sie eine Nummer mit der ret Anweisung.Die Bedeutung von RET in Assembly

So:

Function Proc 
push ax cx 
. 
...body... 
. 
pop cx ax 
ret 2 
Function endp 

Ich verstehe es etwas mit dem zu tun hat, wo der Stapelzeiger am Ende der Funktion zurückgegeben werden sollte?

Bitte, es würde mir wirklich helfen, wenn Sie es leicht erklären könnte.

+6

Assembly ist nicht eine Sprache - jeder Prozessor hat seine eigene. Sie sollten nach einer bestimmten Architektur fragen (x86, so scheint es). – ugoren

+0

Und die Antwort, für x86, ist [hier] (http://download.intel.com/products/processor/manual/325383.pdf) – ugoren

+2

Off-Topic: 'ret' ist eine leistungsstarke kleine Anweisung, die schon lange ist Das Zentrum der Buggy-Software: Es leitet den Kontrollfluss des Programms entsprechend dem Inhalt des Speichers des Call-Stacks. Wenn Sie den Speicher kontrollieren ('strcpy', ich sehe Sie an), steuern Sie den Ablauf der Programmausführung. –

Antwort

14

Ja, aber ret 2 entfernt auch 2 Bytes von Parametern aus dem Stapel. Vermutlich wurde Ihre Funktion wie genannt:

push some_parameter 
call Function 

An dieser Stelle eine cdecl Funktion - eine Funktion „Anrufer bereinigt“ (im Allgemeinen durch C verwendet) - würde add sp, 2 erfordern, „den Stapel aufzuräumen“, das Entfernen von Parameter. Eine solche Funktion würde in einer einfachen ret enden.

A stdcall Funktion, das ist, was du hast, ist eine Funktion „Aufgerufene bereinigt“ (verwendet von Windows-APIs, zum Beispiel) erfordert nicht die add sp, 2 - es wird von den ret 2 geschehen ist.

Wenn Sie es sich nicht bewusst sind, call legt die Rücksprungadresse auf dem Stack (und ret erscheint es aus), so kann man nicht nur pop den Parameter in Ihrer Funktion zu erhalten.

3

Es bedeutet RETurn, wie ein return in High-Level-Sprachen.

Bei den meisten Maschinen wird der vorherige Wert des Programmzählers vor dem Aufruf des Unterprogramms vom Stapel gelöscht und in das PC-Register kopiert.

Für x86, ist das Argument die Anzahl der Parameter auf dem Stapel. Dies trifft nur zu, wenn die verwendete Konvention darin besteht, dass die Subroutine das Zurücksetzen des Stapels übernimmt.

+0

Also was bedeutet die Zahl daneben? –

+0

@RotemMayo Siehe meine Bearbeitung. – alex

+2

Geringfügige Korrektur: Der unmittelbare Operand gibt die Anzahl zusätzlicher _bytes_ an, die bei der Rückgabe aus dem Stapel "entfernt" werden sollen. – Michael

6

als Alex gesagt, bedeutet dies, RETURN. Wenn der Compiler in x86-Assembly diese Zeile erreicht (z. B. am Ende einer Subroutine), wird der Wert last aus dem Stack, der die zurückgegebene Adresse sein soll, ausgegeben und dem IP-Register zugewiesen. Sie können das besser verstehen, indem Sie einen einfachen Assembler-Code schreiben und ihn mit Turbo Debugger kompilieren. Es gibt eine GUI für Assembler, wenn Sie neu sind. Sie können die GUI here finden.

Wenn Sie in einer Subroutine Werte von und zum Stapel pumpen und schieben, sollten Sie die zurückgegebene Adresse speichern, da Sie sie am Ende der Unterroutine vor dem return zurück in den Stapel schieben müssen Linie.

Viel Glück!

12

Lets sagen, ich habe eine Prozedur, um zwei Wörter hinzufügen und lassen Sie die Summe in EAX. Die Wörter sind Argumente, die ich an die Prozedur auf dem Stapel übergeben möchte. ich.e:

addtwob proc 

push ebp 
mov ebp,esp 
mov eax, [ebp+6]  
add eax, [ebp+8] 
pop ebp 
ret 4 

Endp 

[ebp+6] und [ebp+8] Adresse word2 und word1 auf dem Stapel:

push word1 
push word2 
call addtwob 

Das Verfahren etwas aussehen würde. ret 4 kehrt nur wie üblich zurück, fügt aber 4 zum Stack-Pointer hinzu (esp), so dass Sie pop word2pop word1 nicht vom Stapel nach dem Aufruf verlassen müssen, daher reinigt/balanciert der Stack, ohne die vorherigen Pushs zu löschen.

1

Sie scheinen nach einem nahe Rückkehr mit einem Operanden für x86_64 zu fragen. Der Algorithmus, dem die Hardware folgt, wenn der Prozessor in der Nähe von RET auftrifft, ist in Intel instruction set reference manual wie folgt gezeigt;

(* Near return *) 
IF instruction = near return 
    THEN; 
    IF OperandSize = 32 
     THEN 
     IF top 4 bytes of stack not within stack limits 
      THEN #SS(0); FI; //throw protected mode exception 
     EIP ← Pop(); 
     ELSE 
     IF OperandSize = 64 
      THEN 
      IF top 8 bytes of stack not within stack limits 
       THEN #SS(0); FI; //throw protected mode exception 
      RIP ← Pop(); 
      ELSE (* OperandSize = 16 *) 
      IF top 2 bytes of stack not within stack limits 
       THEN #SS(0); FI; //throw protected mode exception 
      tempEIP ← Pop(); 
      tempEIP ← tempEIP AND 0000FFFFH; 
      IF tempEIP not within code segment limits 
       THEN #GP(0); FI; //throw protected mode exception 
      EIP ← tempEIP; 
     FI; 
    FI; 
    IF instruction has immediate operand 
     THEN (* Release parameters from stack *) 
     IF StackAddressSize = 32 
      THEN 
      ESP ← ESP + SRC; 
      ELSE 
      IF StackAddressSize = 64 
       THEN 
       RSP ← RSP + SRC; 
       ELSE (* StackAddressSize = 16 *) 
      SP ← SP + SRC; 
      FI; 
     FI; 
    FI; 
FI; 
  • Nach diesem Algorithmus, wenn eine nahe Rückkehr angetroffen wird, wird Absenderadresse überprüft, ob es in SS Grenzen liegt. Der obere Teil des Stapels wird entsprechend der Operandengröße in RIP oder EIP eingefügt, wenn die Rückgabeadresse gültig ist.

  • Wenn die Operandengröße 16 Bits beträgt, enthält eine temporäre Position eine Popup-Rücksprungadresse, die mit dem Wert 0x0000FFFF UND-verknüpft ist und nach Überprüfung der CS-Grenzwerte in den EIP geladen wird.

  • Als Ihre Frage fragt, was passiert, wenn es einen Operanden für den nahen RET-Befehl Opcode gibt. Dies hängt von der Größe der Stack-Adresse ab. Entsprechend dieser Größe wird RSP ESP oder SP um den Operanden erhöht, und nachdem der gesamte RET-Befehl abgeschlossen ist, wird die Ausführung auf der Hardware abgeschlossen.

+1

'pop cx' ist ein ziemlich klares Zeichen dafür, dass das OP 16-Bit-Code betrachtet. Aus irgendeinem Grund fragen Leute eine Menge Stack Overflow Fragen über 16-Bit-Code. Einige von ihnen machen Spielzeug-Betriebssysteme, die meisten von ihnen nehmen Universitätskurse, die 8086 mit emu8086 aus irren Gründen unterrichten. –