一个有趣的过程 movq %rcx, %gs:0x80000000不能通过编译

简介: # movq %rcx, %gs:0x80000000不能通过编译 今天有同事提问, 为什么 ``` movq %rcx, %gs:0x7fffffff //可以通过编译 movq %rcx, %gs:0x80000000 //不能通过编译 ``` 其实就是一个立即数的差别, 应该是无差的, 好吧, 让我们来研究一下 # 第一步 先看一下```movq %rcx, %g

movq %rcx, %gs:0x80000000不能通过编译

今天有同事提问, 为什么

movq %rcx, %gs:0x7fffffff //可以通过编译
movq %rcx, %gs:0x80000000 //不能通过编译

其实就是一个立即数的差别, 应该是无差的, 好吧, 让我们来研究一下

第一步

先看一下movq %rcx, %gs:0x7fffffff的二进制指令, 因为movq %rcx, %gs:0x80000000不能通过编译, 就不是合法指令, 自然也看不了二进制内容了

  1c:   65 48 89 0c 25 ff ff    mov    %rcx,%gs:0x7fffffff
  23:   ff 7f

第二步

既然65 48 89 0c 25 ff ff ff 7f是mov %rcx,%gs:0x7fffffff, 很容易得到前面65 48 89 0c 25是mov %rcx,%gs, 后面是一个立即数, 那么我们就看看65 48 89 0c 25 80 00 00 00是什么东西

第三步

怎么知道65 48 89 0c 25 80 00 00 00是什么东西呢?
打开o文件, 找到指令的编码位置, 把7f ff ff ff 改成 80 00 00 00, 然后再objdump, 得到

  1c:   65 48 89 0c 25 00 00    mov    %rcx,%gs:0xffffffff80000000
  23:   00 80

由此我们可以得到, 65 48 89 0c 25后面的4字节会被解释成signed int, 再来验证一下, 编译一下mov %rcx,%gs:0xffffffff80000000可以得到65 48 89 0c 25 00 00 00 80

可以得到结论, movq %rcx, %gs:0x80000000被gcc理解成了movq %rcx, %gs:0x0000000080000000

第四步

下面的问题就是为什么movq %rcx, %gs:0x0000000080000000是非法指令
其中一个很容器想到的答案就是, 原来指令65 48 89 0c 25后面是跟4字节的, 现在变成8字节了, 如果还是这种模式的话, 变成了13字节, 应该是太长了, 所以65 48 89 0c 25要变成更短的东西, opcode和register的选择也没这么随意了, 下面的事情就是去查手册了, 还有一种偷懒的方式就是把rcx换成其他寄存器, 把所有的寄存器都试一遍, 看看行不行

结论

movq %r?x, %gs:0x0000000080000000只能使用rax

movq %rcx, %gs:0x7fffffff, movq %rcx, %gs:0x80000000是被编码成64位基地址和32位整数或者64位整数相加,

先讨论位编码成32位整数的情况,

如果我是设计师的话, 也倾向于把后面的这个32位设计成signed, 这样寻址过程中, 又能向前, 又能向后

所以movq %rcx, %gs:0x7fffffff是合法的

movq %rcx, %gs:0x80000000 gcc报告错误是因为这个等价于movq %rcx, %gs:0x0000000080000000, 0x0000000080000000已经超出32位signed的范围了, 不能编码成64位基地址和32位整数相加, 只能编码成64位基地址和64位整数相加

这样后面的这个64位整数就要被编码进指令里面去, 比之前的指令多了4个字节, 所以前面的寄存器, opcode的编码就少了, 不能随意的选择寄存器, 只能默认rax来操作, 也就是mov变成了movabs

所以movq %rax, %gs:0x80000000是合法的

目录
相关文章
|
安全 Java 数据处理
Python网络编程基础(Socket编程)多线程/多进程服务器编程
【4月更文挑战第11天】在网络编程中,随着客户端数量的增加,服务器的处理能力成为了一个重要的考量因素。为了处理多个客户端的并发请求,我们通常需要采用多线程或多进程的方式。在本章中,我们将探讨多线程/多进程服务器编程的概念,并通过一个多线程服务器的示例来演示其实现。
|
2月前
|
存储 人工智能 缓存
AI不稳定不是工程Bug,是一场系统性误读——意图共鸣科技行业洞察
过去三年AI狂卷参数与算力,却困于“Demo惊艳、上线翻车”。症结在于误读“AI稳定性”——它非传统软件不宕机,而是大模型在行为分寸、长期记忆、责任可溯、商业可持续四维的结构性缺失。意图共鸣科技正深耕此深水区。
270 6
|
6月前
|
数据采集 机器学习/深度学习 测试技术
Python断言:代码中的"安全卫士"如何守护程序健康
本文深入解析Python断言(assert)机制,阐述其作为开发阶段“程序免疫系统”的核心价值:通过简洁语法(如`assert 0<=rate<=1`)主动检测内部不变量,快速暴露逻辑错误。涵盖四大应用场景、五大最佳实践及真实案例,强调断言≠异常处理,禁用于用户输入验证,重在提升代码健壮性与可维护性。(239字)
475 6
|
10月前
|
JavaScript Java 关系型数据库
基于springboot的高校运动会系统
本系统基于Spring Boot、Vue与MySQL,实现高校运动会报名、赛程安排及成绩管理的全流程信息化,提升组织效率,杜绝信息错漏与冒名顶替,推动体育赛事智能化发展。
|
11月前
|
存储 人工智能 API
阿里 Qoder 新升级,Repo Wiki 支持共享、编辑和导出
Qoder 是阿里巴巴推出的 Agentic 编程平台,集成顶尖编程模型,具备强大上下文工程能力,可一次检索10万代码文件,大幅提升软件开发效率。其 Repo Wiki 功能自动生成结构化文档,支持共享、编辑与导出,助力知识沉淀与团队协作。
|
机器学习/深度学习 安全 数据处理
泰坦尼克号乘客生存情况预测分析1
泰坦尼克号乘客生存情况预测分析1
1009 2
|
Oracle 关系型数据库 数据库
【YashanDB 知识库】使用 Reverse 索引的解决自增序列做索引,插入性能大幅提升
【YashanDB 知识库】使用 Reverse 索引的解决自增序列做索引,插入性能大幅提升
|
人工智能 安全 大数据
ARM 服务器上安装 OpenEuler (欧拉)
openEuler 是华为于2019年开源的操作系统,支持多种处理器架构,包括X86和鲲鹏。截至2020年底,openEuler 拥有3万社区用户、2万多个拉取请求、2000多名贡献者和7032款软件。openEuler 提供高效、稳定、安全的系统,适用于数据库、大数据、云计算和人工智能等场景。本文介绍了在神州鲲泰 R522 服务器上安装 openEuler 的详细步骤,包括下载镜像、配置 RAID 和 BIOS 设置等。
2088 0
ARM 服务器上安装 OpenEuler (欧拉)
|
机器学习/深度学习 存储 C语言
【C语言篇】C语言常考及易错题整理DAY1
swap函数调用时用的是全局变量,主函数中定义的变量只在主函数中有效,因为主函数也是一个函数,它与其他函数是平 行关系;输出语句这里,考虑局部优先的原则。
495 1
|
数据中心 云计算 网络架构