wake-up-neo.com

Die Bedeutung von RET in der Montage

Ich bin sehr neu in Assembly und verstehe nicht, was es genau bedeutet, wenn Sie am Ende einer Prozedur mit der Anweisung ret eine Zahl schreiben. 

So was:

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

Ich verstehe, dass es etwas damit zu tun hat, wohin der Stackzeiger am Ende der Funktion zurückkehren soll? 

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

20
Rotem Mayo

Ja, aber ret 2 entfernt auch 2 Byte Parameter aus dem Stack. Vermutlich wurde Ihre Funktion so genannt:

Push some_parameter
call Function

An diesem Punkt würde eine cdecl-Funktion - eine "Aufrufer-Bereinigungs" -Funktion (im Allgemeinen von C verwendet) - erfordern, dass add sp, 2 "den Stack aufräumt", wodurch der Parameter entfernt wird. Eine solche Funktion würde in einer einfachen Variable ret enden.

Eine stdcall-Funktion, die Sie haben, ist eine "Callee-Clean-Up" -Funktion (die beispielsweise von Windows-APIs verwendet wird) erfordert nicht den add sp, 2 - dies wurde von ret 2 ausgeführt.

Wenn Sie sich dessen nicht bewusst sind, setzt call die Rücksprungadresse auf den Stapel (und ret ruft sie ab), sodass Sie nicht einfach pop den Parameter in Ihre Funktion bekommen können.

19
Frank Kotler

Nehmen wir an, ich habe eine Prozedur, um zwei Wörter hinzuzufügen und die Summe in EAX zu belassen. Die Wörter sind Argumente, die ich an die Prozedur auf dem Stapel übergeben möchte. das heißt:

Push Word1
Push Word2
call addtwob

Die Prozedur würde ungefähr so ​​aussehen:

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 Stack .ret 4 wird einfach wie üblich zurückgegeben, fügt jedoch dem Stackzeiger (esp) 4 hinzu, so dass Sie nach dem Abrufen des Anrufs pop Word2pop Word1 nicht aus dem Stack aussteigen müssen reinigt/balanciert den Stack, ohne dass die vorherigen Push-Aktionen ausgelöst werden müssen.

16
Nhat M Le

Wie Alex sagte, bedeutet dies RETURN . Wenn der Compiler in x86 Assembly diese Zeile erreicht (beispielsweise am Ende einer Subroutine), holt er den last - Wert aus dem Stack, der dies tun soll die zurückkehrende Adresse sein und dem IP-Register zugewiesen werden. Sie können dies besser verstehen, indem Sie einen einfachen Assembler-Code schreiben und ihn mit Turbo Debugger kompilieren. Es gibt eine GUI für Assembler, falls Sie neu sind. Sie finden die GUI hier .

Wenn Sie in einer Subroutine Werte aus dem und in den Stack laden und verschieben, sollten Sie die zurückgegebene Adresse speichern, da Sie sie am Ende der Subrouting vor der return-Zeile in den Stack zurückschieben müssen.

Viel Glück!

8
c0ldsh3ll

Dies bedeutet RETurn wie ein return in Hochsprachen.

Bei den meisten Maschinen wird der vorherige Wert des Programmzählers vor dem Aufrufen der Subroutine aus dem Stapel herausgenommen und in das PC-Register kopiert.

Bei x86 ist das Argument die Anzahl der Parameter im Stack. Dies gilt nur, wenn die übliche Konvention das Zurücksetzen des Stapels durch die Subroutine handhaben soll.

3
alex

Sie scheinen nach einem near return mit einem Operanden für x86_64 zu fragen. Der Algorithmus, dem die Hardware folgt, wenn der Prozessor in der Nähe von RET angetroffen wird, ist im Handbuch für den Intel-Befehlssatz gezeigt lautet wie folgt;

(* 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;
  • Gemäß diesem Algorithmus wird bei der Rückkehr in die Nähe der Rückkehr die Adresse überprüft, ob sie sich in SS-Grenzen befindet. Der obere Rand des Stapels wird entsprechend der Operandengröße in RIP oder EIP eingefügt, sofern die Rücksprungadresse gültig ist.

  • Wenn die Operandengröße 16 Bit beträgt, enthält ein temporärer Speicherort eine Popping-Return-Adresse, die mit dem Wert 0x0000FFFF UND-verknüpft ist und nach Überprüfung der CS-Grenzwerte in den EIP geladen wird. 

  • Bei Ihrer Frage werden Sie gefragt, was passiert, wenn der Operationscode für den Near RET-Befehl einen Operanden enthält. Dies hängt von der Adressgröße des Stacks ab. Entsprechend dieser Größe wird der RSP ESP oder SP um den Operanden erhöht, und nachdem der nahe RET-Befehl abgeschlossen ist, wird die Ausführung auf der Hardware abgeschlossen. 

1
gokhanbas.eee