Значение RET в сборке - программирование
Подтвердить что ты не робот

Значение RET в сборке

Я очень новичок в сборке, и я не понимаю, что именно означает, когда в конце proc вы пишете число с помощью оператора ret.

Вот так:

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

Я понимаю, что это как-то связано с тем, куда указатель стека должен вернуться в конце функции?

Пожалуйста, это действительно помогло бы мне, если бы вы могли легко объяснить это.

4b9b3361

Ответ 1

Да, но ret 2 также удаляет из байта 2 байта параметров. Предположительно, ваша функция вызывалась как:

push some_parameter
call Function

В этот момент функция cdecl - функция "очиститель звонящего" (обычно используется C) - потребовала бы add sp, 2 "очистить стек", удалив параметр. Такая функция завершится простым ret.

Функция A stdcall, которая есть у вас, - это функция "очистка отклонений" (используемая, например, Windows API), не требует add sp, 2 - она ​​была выполнена с помощью ret 2.

Если вы не знаете об этом, call помещает обратный адрес в стек (и ret выдает его), поэтому вы можете просто pop получить параметр внутри вашей функции.

Ответ 2

Допустим, у меня есть процедура добавления двух слов и оставить сумму в EAX. Слова являются аргументами, которые я хочу передать процедуре в стеке. то есть:

push word1
push word2
call addtwob

Процедура будет выглядеть примерно так:

addtwob proc

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

Endp

[ebp+6] и [ebp+8] адрес word2 и word1 в стеке. ret 4 просто возвращается, как обычно, но затем добавляет 4 к указателю стека (esp), поэтому вам не нужно pop word2 pop word1 покинуть стек после возврата из вызова, поэтому он очищает/балансирует стек без необходимо нажать предыдущие нажатия.

Ответ 3

Как сказал alex, это означает RETURN. В сборке x86, когда компилятор достигает этой строки (например, в конце подпрограммы), она выталкивает значение last из стека, которое должно быть возвращающим адресом, и назначает его к регистру ИС. Это можно понять, написав простой код ассемблера и скомпилировав его с помощью Turbo Debugger. Там графический интерфейс для ассемблера, если вы новичок в этом. Здесь вы можете найти графический интерфейс .

Когда вы вставляете и выталкиваете значения из и в стек, когда находитесь в подпрограмме, вы должны сохранить возвращаемый адрес, потому что в конце подпрограммы вам нужно вставить его обратно в стек до return.

Удачи!

Ответ 4

Это означает, что RETurn, например, return на языках высокого уровня.

На большинстве машин он выдает предыдущее значение счетчика программы перед тем, как ввести подпрограмму в стек и скопировать ее в регистр ПК.

Для x86 аргумент представляет собой количество параметров в стеке. Это применимо только в том случае, если в используемом соглашении используется подпрограмма для сброса стека.

Ответ 5

Кажется, вы спрашиваете о ближайшем возврате с операндом для x86_64. Алгоритм, который сопровождается аппаратным обеспечением, когда рядом с RET встречается процессор, показан в Справочное руководство по набору инструкций Intel:

(* 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;
  • В соответствии с этим алгоритмом, когда встречается почти возврат, адрес возврата проверяется, находится ли он в пределах SS. Вершина стека выставляется в RIP или EIP в соответствии с размером операнда, если адрес возврата действителен.

  • Если размер операнда равен 16 битам, временное местоположение удерживает возвращенный адрес возврата, который имеет значение AND, со значением 0x0000FFFF и загружается в EIP после проверки пределов CS.

  • Как ваш вопрос задает вопрос о том, что произойдет, если есть операнд для кода операции ближней команды RET. Это зависит от размера адреса стека. В соответствии с этим размером RSP ESP или SP увеличивается на операнд, и после того, как все инструкции RET завершены, выполняются на аппаратном обеспечении.