GCC/X86,相对跳转问题

2024-02-23

我正在尝试在 x86 程序集中进行相对跳转,但是我无法让它工作。似乎由于某种原因,我的跳跃不断被重写为绝对跳跃或其他东西。

我想做的一个简单的示例程序是这样的:

.global main

main:
    jmp 0x4
    ret

由于 jmp 指令有 4 个字节长,并且相对跳转是从跳转地址 + 1 开始的偏移,因此这应该是一个奇特的无操作。但是,编译并运行此代码将导致分段错误。

对我来说真正的困惑是,将其编译到对象级别,然后反汇编对象文件表明汇编器看起来正确地执行了相对跳转,但在文件编译后链接器将其更改为另一种类型的跳转。

例如,如果上述代码位于名为 asmtest.s 的文件中:

$gcc -c asmtest.s
$objdump -D asmtest.o

... Some info from objdump
00000000 <main>:
   0:    e9 00 00 00 00           jmp    5 <main+0x5>
   5:    c3                       ret   

这看起来汇编器正确地进行了相对跳转,尽管 jmp 指令填充了 0 值得怀疑。

然后我使用 gcc 链接它然后反汇编它并得到这个:

$gcc -o asmtest asmtest.o
$objdump -d asmtest

...Extra info and other disassembled functions
08048394 <main>:
 8048394:        e9 6b 7c fb f7      jmp   4 <_init-0x8048274>
 8048399:        c3                  ret

在我看来,链接器重写了 jmp 语句,或者将 5 替换为另一个地址。

所以我的问题归结为,我做错了什么?

我是否错误地指定了偏移量?我是否误解了相对跳转的工作原理? gcc 是否试图确保我不会在代码中做危险的事情?


实际上,汇编器认为你正在尝试做一个absolute跳。但是,那jmp操作码在金属级别是相对的。因此,汇编器无法知道在 0xe9 字节之后要写入什么,因为汇编器不知道代码最终会到达哪个地址。

汇编器不知道,但链接器知道。所以汇编器写在asmtest.o标头某处对链接器的请求,如下所示:“当您知道代码将在哪个地址加载时,调整 0xe9 之后的这些字节,以便它们适合从该点跳转(使用相对寻址) ) 到绝对地址“4””。链接器就是这么做的。它看到 0xe9 位于地址 0x08048394,下一个操作码位于 0x08048399,并且它计算出:要从 0x08048399 到 0x00000004,必须减去 0x08048395,这相当于添加(在 32 位机器上)0xf7fb7c6b。因此,生成的二进制文件中的“6b 7c fb f7”序列。

您可以像这样“手动”编码相对跳转:

.global main
main:
    .byte 0xe9
    .long 0x4
    ret

因此,汇编器不会注意到你的 0xe9 实际上是一个jmp,并且它不会试图比你聪明。在二进制文件中,您将获得所需的“e9 04 00 00 00”序列,并且没有链接器交互。

注意上面的代码可能会崩溃,因为相对偏移量是从地址开始算的之后立马偏移量(即下一个操作码的地址,这里ret)。这将在无人区跳转 4 个字节后ret似乎有可能出现段错误或奇怪的情况。

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

GCC/X86,相对跳转问题 的相关文章

随机推荐

  • Symfony2 计算与另一个实体相关的实体字段

    我有 2 个实体 作者和书籍 1 个作者可能有很多书 我想在表格中显示每个作者有多少本书 每个作者的数量不同 我已经看过了this https stackoverflow com questions 17665271 counting th
  • PHP usort 不会对类进行排序

    这是要排序的元素数组的示例 items array 0 gt object stdClass 8 public id gt string 110 length 3 public brand id gt string 18 length 2
  • Python print 与 Javascript console.log()

    在Python中 print 1 2 n 3 4 会打印 1 2 3 4 在 JavaScript 中 console log 1 2 n 3 4 prints 1 2 n 3 4 与上面的 Python 等效的 Javascript 语句
  • 无法打开相机连接到相机时发生错误:0

    我开始开发一个应用程序 我需要使用手机的相机 当我使用 Camera open 方法时 无论是否带有cameraId 它都会返回错误 连接到相机时发生错误 0 我的 AndroidManifest xml 是
  • 如何在html页面中以格式化的方式显示html代码[重复]

    这个问题在这里已经有答案了 我的网站是一个简单的教育网站 我想以格式化的方式在我的网页中显示 HTML 代码 就像在编辑器中一样 我的意思是 HTML 标签应该以与剩余文本等不同的颜色显示 这是来自另一个网站的代码片段 我想要我的网页的输出
  • 使用 google guava 的 CacheBuilder 的 scala 2.10 类型不匹配

    我正在 scala 2 10 1 中为我的一些实体编写通用缓存 目前 我正在使用 google Guava 的 CacheBuilder 因为 scala 生态系统中没有太多选择 Code trait CachedEntity E lt K
  • SurfaceView隐藏屏幕上的其他组件

    我正在创建一个 FrameLayout 类型的布局 在其中添加两个视图 两个视图分别是GLSurfaceView和SurfaceView的对象 根据有关 SurfaceView 的 Android 开发人员文档 表面是 Z 排序的 因此它位
  • 如何用 pandas DataFrame 中之前和后续值的平均值替换 NaN?

    如果我有一些缺失值 并且我想用之前和之后值的平均值替换所有 NaN 我该怎么做 我知道我可以使用pandas DataFrame fillna with method ffill or method bfill 用前面或后面的值替换 NaN
  • 使用 AVPlayer 音频播放 AVMutableComposition 不同步

    我有一个带有 2 个音频轨道和 1 个视频轨道的 AVMutableComposition 我使用该合成从 mov 文件中串接大约 40 个不同的视频剪辑 将每个剪辑的视频内容放入合成的视频轨道中 将音频放入音轨中 我用于音乐的第二个音轨
  • 使用异步延迟加载属性

    我已经学会了在我的存储库中延迟加载属性 现在我想这样做 但我还需要从网页加载一些内容 使用 Httpclient 这意味着我的属性将是异步的 public async Task
  • 荷兰国旗 - 不适用于更大的阵列

    我的下面的荷兰国旗解决方案似乎不适用于仅包含 3 个元素 0 1 和 2 的给定输入数组 如果我减小数组的大小 它就会起作用 我无法识别错误 我错过了什么吗 class DNF public static void sort int arr
  • WordPress WP_Query 通话帖子和页面

    我设置了一个功能滑块 用于绘制标记为 功能 的帖子 my query new WP Query array showposts gt 3 tag gt feature 可以在帖子和页面中绘制吗 我知道你可以用以下方式绘制页面 post ty
  • OpenCL 产生错误的计算

    我一直尝试使用openCL做一些计算 但结果不正确 我输入了三个 float3 如下所示 300000 0 0 300000 300000 0 300000 300000 300000 进入这个内核 kernel void gravitat
  • 如何在运行的容器内获取AWS Fargate任务实例元数据?

    当任务在 AWS Fargate 内部启动时 它有一个用于 Cloudwatch 日志的任务 ID guid 并且可以用作唯一的 运行 ID 我正在将 NET Core 应用程序启动到 AWS 容器中 并希望找到一种编程方式来提取任务 ID
  • System.Private.ServiceModel 的问题

    我创建了一个 Core 3 1 应用程序 它使用基于 net 标准 2 0 的 Web 服务 在本地开发环境中一切正常 在我将其部署到 UAT IIS 上之前 我收到以下异常 Exception System IO FileNotFound
  • 在 Mac OS X 10.6.8 上用什么来编译和模拟 Verilog 程序?

    作为教学大纲的一部分 我需要模拟 Verilog 程序 但是 我的大学使用 Xilinx ISE 但它不适用于 Mac 因此 请帮助我提供最好的软件以及有关如何安装和使用它们的一些详细步骤 你可以尝试伊卡洛斯 Verilog http iv
  • Android tab 片段不调用 OnCreateView 从 tab2 切换到 tab1

    这是选择 3 选项卡式布局时 Android Studio 自动生成的代码 问题是当它从第一个选项卡开始时 它会调用onCreateView in class PlaceholderFragment 当我切换到第二个选项卡时 它会再次为该选
  • 嵌套条件与复合条件

    这两个例子中哪一个表现更好 示例1 if condition 1 if condition 2 do something 示例2 if condition 1 and condition 2 do something 如果有的话 差异可以忽
  • 如何跳过空格但将其用作解析器组合器中的标记分隔符

    我正在尝试构建一个小型解析器 其中标记 幸运的是 从不包含空格 空白 空格 制表符和换行符 本质上是标记分隔符 除了有括号等的情况 我正在延长RegexParsers班级 如果我打开skipWhitespace当下一个标记与前一个标记的正则
  • GCC/X86,相对跳转问题

    我正在尝试在 x86 程序集中进行相对跳转 但是我无法让它工作 似乎由于某种原因 我的跳跃不断被重写为绝对跳跃或其他东西 我想做的一个简单的示例程序是这样的 global main main jmp 0x4 ret 由于 jmp 指令有 4