【问题标题】:The meaning of RET 2 in assemblyRET 2 在汇编中的含义
【发布时间】:2013-07-11 19:41:41
【问题描述】:

我对汇编很陌生,我不明白在 proc 结束时用ret 语句写一个数字的确切含义。

像这样:

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

我知道这与函数结束时堆栈指针应返回的位置有关吗?

它有什么作用?

【问题讨论】:

  • Assembly 不是一种语言 - 每个处理器都有自己的。您应该询问特定架构(似乎是 x86)。
  • 题外话:ret 是一个功能强大的小指令,长期以来一直是利用漏洞软件的中心:它根据调用堆栈的内存内容指导程序的控制流。如果你控制了内存(strcpy,我在看着你),你就控制了程序的执行流程。

标签: assembly x86


【解决方案1】:

是的,但ret 2 也会从堆栈中删除 2 个字节的参数。大概,你的函数被称为:

push some_parameter
call Function

此时,cdecl 函数 - “调用者清理”函数(通常由 C 使用) - 将需要 add sp, 2 “清理堆栈”,删除参数。这样的函数将以纯 ret 结尾。

您所拥有的stdcall 函数是“被调用者清理”函数(例如,由 Windows API 使用)不需要 add sp, 2 - 它已由 @ 完成987654328@.

如果您不知道,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] 地址 word2word1 在堆栈上。 ret 4 只是像往常一样返回,但随后将 4 添加到堆栈指针 (esp),因此您不必在从调用返回后将 pop word2 pop word1 移出堆栈,因此它会清理/平衡堆栈而不需要弹出之前的推送。

    【讨论】:

    • 所以 pop 清除已设置的 ebp,ret 清除返回地址并在 ret 清除额外的 4 个字节(即两个字)后设置“4”。这是正确的吗?
    【解决方案3】:

    正如亚历克斯所说,这意味着返回。 在 x86 汇编中,当编译器到达这一行时(例如,在子程序的末尾),它会从堆栈中弹出 last 值,该值应该是返回地址,并分配给它到 IP 注册。您可以通过编写简单的汇编代码并使用 Turbo Debugger 进行编译来更好地理解这一点。如果您不熟悉汇编程序,则有一个 GUI。您可以找到图形用户界面here

    当您在子程序中从堆栈中弹出和压入值时,您应该存储返回地址,因为在子路由结束时您需要在@987654322 之前将其压入堆栈@线。

    祝你好运!

    【讨论】:

      【解决方案4】:

      这意味着返回,就像高级语言中的return

      在大多数机器上,它会在进入子程序之前从堆栈中弹出程序计数器的先前值并将其复制到 PC 的寄存器中。

      对于 x86,参数是堆栈上的参数数量。这仅适用于使用的约定是让子例程处理重置堆栈的情况。

      【讨论】:

      • 那么旁边的数字是什么意思?
      • 小修正:直接操作数指定返回时要从堆栈“弹出”的额外字节数。
      • @Michael 谢谢,这就是我的意思,但可能并不明显。
      【解决方案5】:

      对于 x86 32 位“ret 的可选数字(16 位或 32 位)参数指定从堆栈中弹出返回地址后要释放的堆栈字节或字的数量。通常,这些字节或字是用作被调用过程的输入参数。"-- https://docs.oracle.com/cd/E19455-01/806-3773/instructionset-67/index.html

      所以它首先弹出返回地址,然后可选数字是指在弹出返回地址后增加堆栈的字节数。

      ret 4 在 32 位模式下总共是 esp+=8,包括弹出 4 字节返回地址和调用者推送的 4 字节。

      【讨论】:

      • 从堆栈中删除字节会增加 ESP,而不是 dec。所以ret N 就像一个普通的ret 然后add esp, N (但没有修改FLAGS)。
      【解决方案6】:

      您似乎在询问 带有 x86_64 操作数的接近回报Intel instruction set reference manual中处理器遇到接近RET时硬件遵循的算法如下:

      (* 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 位,则临时位置保存弹出的返回地址,该地址与值 0x0000FFFF 进行“与”运算,并在检查 CS 限制后加载到 EIP 中。

      • 正如您的问题所问的,如果近 RET 指令操作码有操作数会发生什么。这取决于堆栈地址的大小。根据该大小,RSP ESP 或 SP 由操作数增加,并且在所有近 RET 指令在硬件上完成执行之后。

      【讨论】:

      • pop cx 是一个非常明显的迹象,表明 OP 正在查看 16 位代码。出于某种原因,人们会问很多关于 16 位代码的 Stack Overflow 问题。他们中的一些人正在制作玩具操作系统,他们中的大多数人出于某种疯狂的原因正在学习用 emu8086 教授 8086 的大学课程。
      猜你喜欢
      • 2022-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-20
      • 1970-01-01
      • 1970-01-01
      • 2015-09-04
      • 2013-10-18
      相关资源
      最近更新 更多