RET后的指令一定是CALL后的指令吗?

2023-12-03

在行为良好的 C 程序中,返回语句 (RET) 是否始终返回到 CALL 语句后面的指令?我知道这是默认设置,但我想检查是否有人知道或记得不适用此标准的真实示例(常见编译器优化或其他事情......)。有人告诉我,函数指针可能会发生这种情况(函数指针会将值放在堆栈上,而不是 CALL...我搜索了它,但没有在任何地方看到解释)。

让我尝试更好地解释我的问题。我知道我们可以使用其他结构来更改执行流程(包括操作堆栈)...我知道如果我们更改写入堆栈上的返回地址,执行流程将更改为写入堆栈上的地址。我需要知道的是:是否有任何不寻常的执行情况,下一条指令不是CALL后面的指令?我的意思是,我想确保它不会发生,除非发生意外情况(例如内存访问冲突会导致结构化异常处理程序)。

我担心的是,一般的商业应用程序是否始终遵循上述模式。请注意,在这种情况下,我对异常有一种执着(重要的是要知道在这种情况下它们是否存在,对于我正在开发为硕士学位课程学科的研究项目)。例如,我知道编译器有时可能会将 RET 更改为 JMP(尾部调用优化)。我想知道这样的事情是否会改变 RET 之后执行的指令的顺序,主要是 CALL 是否总是位于 RET 之后执行的指令之前。


CALL子程序地址相当于
PUSH下一条指令地址 + JMP子程序地址.

同时,推送地址几乎相当于
SUB xSP,指针大小 + MOV [xSP],地址.

SUB xSP,指针大小可以替换为PUSH.

RET几乎相当于
JMP [xSP]其次是ADD xSP,指针地址位于 JMP 领先的位置。

And ADD xSP,指针地址可以替换为POP.

所以,你可以看到编译器有什么样的基本自由。哦,顺便说一句,它可以优化您的代码,使您的函数完全内联,并且既不会调用它,也不会从它返回。

虽然有些反常,但使用针对平台(CPU 和操作系统)高度特定的指令和技术来设计更奇怪的控制传输并非不可能。

您可以使用IRET代替CALL and RET对于控制转移,前提是您将适当的内容放入指令的堆栈中。

您可以使用WindowsStructured Exception Handling导致 CPU 异常(例如除以 0、页面错误等)的指令将执行转移到异常处理程序,并且控制权可以从那里转移回同一指令或下一个或下一个异常处理程序或任何位置。并且大多数x86指令都会导致CPU异常。

我确信还有其他不寻常的方式可以在子例程/函数之间进行控制传输、从子例程/函数内部传输以及在子例程/函数内进行控制传输。

类似这样的代码也并不罕见:

...
CALL A
A: JMP B
db "some data", 0
B: CALL C ; effectively call C with a pointer to "some data" as a parameter.
...

C:
; extracts the location of "some data" from the stack and uses it.
...
RET

在这里,第一次调用不是子例程,它只是将代码中间的数据地址放入堆栈的一种方法。

这可能是程序员会写的,而不是编译器会写的。但我可能错了。

我想说的是,你不应该期望拥有CALL and RET作为进入和离开子例程的唯一方法,您不应期望它们仅用于此目的并相互平衡。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

RET后的指令一定是CALL后的指令吗? 的相关文章

随机推荐

  • 如何以编程方式使折线图点处于活动/突出显示状态

    我使用的是 Chart js 2 0 beta2 页面和滑块上有几个折线图 我想突出显示每个折线图上与滑块位置匹配的数据点 它们都具有相同的点数 我不知道如何轻松地在代码中激活一个点 感谢您的任何提示 2 0 测试版解决方案 扩展您选择的图
  • 来自 JavaScript 的 JavaFX WebView 向上调用不起作用

    我有一个 JavaFX WebView 想要从 Web 视图中显示的 test html 调用 JavaBridge 类的方法 hello 为什么这不起作用 我确保 桥 对象仅在页面完全呈现时添加到 window object 因此这可能不
  • 能够在 print_r() 的输出中看到变量,但不确定如何在代码中访问它

    我用谷歌搜索 安装了 Devel Drupal for Firebug 但我找不到它 I found what我想要 我知道where这是 我只是不知道how为拿到它 为实现它 我将把它放在代码括号中 但 Devel 告诉我文件名 我想将其
  • 如何打印字符串中的每个字符?

    有没有一种方法可以一次从输入中读取一个字符并对其进行处理 而不需要对词汇进行标记 字符串上的 toCharArray 函数在这里可能很有用 for char c s toCharArray System out println c 并仅打印
  • 广播接收器作为 Android 中的内部类

    在我的代码中有一个扩展的内部类BroadcastReceiver 我已将以下行添加到AndroidManifest xml
  • 导入库项目时出现 NoClassDefFoundError

    我目前正在使用版本 4 6 1 Windows Vista Eclipse 编写一个单元测试项目 我的项目分为 3 部分 A 单元测试应用程序 类型 CLDC应用程序 B 待测试应用 类型 CLDC应用 C 一个库项目 类型 library
  • Portlet 中的 YUI 版本冲突问题

    我正在从 portlet 加载 yui js 3 3 0 版本文件 但 liferay 使用 3 2 0 yui js 文件 所以每当我加载该页面时 就会出现 js 错误 G ENV loaded VERSION 未定义 此错误出现在 yu
  • Struts2教程不起作用

    我正在学习struts2 我根据以下内容尝试我的 hello world 项目tutorial然后我在 eclipse 中运行代码 但这不起作用 控制台显示很多错误 第一个如下 com opensymphony xwork2 util lo
  • Iss 声明无效 Keycloak

    我使用 keycloak 服务登录我的网络应用程序 用作具有 oauth 2 0 安全性的后端 spring 当我使用从 keycloak 获得的不记名令牌向邮递员发出请求时 它给了我一个错误 401 并且也在旁边的答案文本中www Aut
  • 通过安全规则中的某个子值限制查询

    我正在努力想出构建部分数据库及其相关安全规则的最佳方法 我有聊天组 并且可以随时将用户添加到这些组中 当用户添加到组中时 他们应该只能检索发送的消息after那 他们不应该检索在他们 用户 添加到组之前发送的任何消息 我的第一种方法错误地假
  • 是否可以在离子侧边栏中使用幻灯片

    我正在用 ionic 构建一个移动应用程序 我想通过放置幻灯片来制作一个类似松弛的侧面菜单 例如 当您单击主菜单项时 它将像 slack 一样在侧菜单中滑出另一张幻灯片 我尝试在离子菜单中使用离子幻灯片 但幻灯片不起作用 请查看屏幕截图 这
  • C++17 中的通用工厂机制

    我想为一组派生类实现一个通用工厂机制 它不仅允许我通用地实现工厂函数来创建该类的对象 而且还允许其他模板类的创建者将派生类之一作为模板参数 理想情况下 解决方案将仅使用 C 17 功能 无依赖项 考虑这个例子 include
  • PHP 中按位解压

    我想通过一个奇怪的 8 8 8 7 位序列将一个二进制字符串解压到一个数组中 对于正常的 8 8 8 8 序列 我可以轻松地执行类似的操作 b unpack C data for i 0 count sizeof b i lt count
  • 在 cocoa touch 中实现基于触摸的旋转

    我想知道在我的 iPhone 应用程序中实现基于旋转的拖动运动的最佳方法是什么 我有一个 UIView 当用户手指触摸视图并移动它时 我希望围绕其中心旋转 把它想象成一个需要用手指调节的表盘 基本问题归结为 1 我应该记住调用touches
  • Spring Boot 服务器在 main 方法执行后停止

    Spring Boot v1 3 3 RELEASE 应用程序在主类执行后停止 None
  • 使用python将txt转换为xlsx时出错

    我的代码如下 import csv import openpyxl import sys def convert input path output path Read a csv file with no quoting and save
  • 强制导航栏元素保持在一行

    我不想要我的元素引导导航栏 to 保持一队在每个宽度 我知道这个问题已经被问过几次我尝试了各种解决方案 但没有人适合我的情况 这是我的代码 head navbar width 100 white space nowrap display i
  • 即使设置 c3p0.testConnectionOnCheckout=true 后,与 MySQL 的数据库连接也会超时

    我有一个使用 hibernate v3 6 4 的应用程序 并由 C3P0 v0 9 1 2 提供连接池 问题是 如果我进行数据库查询 并且应用程序进程 以及 C3P0 池 的运行时间超过了 MySQL wait timeout 值 我会遇
  • 在 Python 中转置文本文件

    我有一个文本文件 我想使用 Python 转置它 例如 给定以下文件 asdfg qwert 我希望脚本的输出是一个文本文件 其中包含 aq sw de fr gt 最简单 最 Pythonic 的方法是什么 我自己能想到的最多的就是将第一
  • RET后的指令一定是CALL后的指令吗?

    在行为良好的 C 程序中 返回语句 RET 是否始终返回到 CALL 语句后面的指令 我知道这是默认设置 但我想检查是否有人知道或记得不适用此标准的真实示例 常见编译器优化或其他事情 有人告诉我 函数指针可能会发生这种情况 函数指针会将值放