从机器码理解RIP 相对寻址
本作品采用知识共享署名 4.0 国际许可协议进行许可。转载联系作者并保留声明头部与原文链接https://luzeshu.com/blog/rip-relative-addressing
本博客同步在 http://www.cnblogs.com/papertree/p/6298763.html
1. 情景
在调试linux-3.0.0内核源码过程中,碰到一处lea指令,略有疑问。
代码如下(路径linux/arch/x86/boot/compressed/head_64.S):
249 /*
250 * Copy the compressed kernel to the end of our buffer
251 * where decompression in place becomes safe.
252 */
253 pushq %rsi
254 leaq (_bss-8)(%rip), %rsi
255 leaq (_bss-8)(%rbx), %rdi
256 movq $_bss /* - $startup_32 */, %rcx
257 shrq $3, %rcx
258 std
259 rep movsq
260 cld
261 popq %rsi
下图1-1是调试过程中的CPU上下文:

图1-1
从“mov rcx,0x243e80”中可以看到,_bss的值为0x243e80的,这是_bss这个symbol在进行汇编时,其所在的section内的偏移位置。
从“lea rdi,[rbx+0x243e78]”中可以看到,加到%rbx的值是_bss-8,这跟汇编源代码是一致的。
而从“lea rsi,[rip+0x243c30]” 中可以看到,加到%rip的偏移值并不是_bss-8 的值。
先说明一点,这个section是加载在0x1000000的内存位置,所以0x1000241这条指令,相对于所在section的起始偏移是0x241。
那么,上面的0x243c30这个值,是由(_bss-8)再减去0x248(下一条指令相对于section的起始偏移值)而得来。
那么,前后两条看起来十分相似的汇编代码为什么有这样的区别呢?
2. RIP的特殊性以及PIC(位置无关代码)
因为RIP寄存器存放着当前指令的地址,所以有它的特殊性。
比如上面的%rip + displacement,其中displacement存放的如果是_bss这个symbol与该指令的“距离值”,那么不管这段代码所在的section装载到哪个位置,都可以通过这个计算,访问到_bss实际装载的位置。
比如section装载在0x1000000,那么指令的%rip为0x1000241,_bss的值为0x1243c30。
而如果装载在0x5000000,那么指令的%rip为0x5000241,_bss的值为0x5243c30。
那么如果displacement存放的是_bss与指令之间的距离值,那么不管实际加载到哪个位置,都可以访问到实际的_bss位置。
这里解释了上面的问题 —— 这两条相似汇编代码的区别,正好利用rip的特殊性,实现了PIC的功能。
但是,还是有疑问。这里的解释仅仅是解释了displacement为什么有“距离值”和“实际值”两种情况,这里的区别似乎只是停留在汇编层面,因为gas汇编器就可以这样实现,当发现base register是%rip,那么displacement就使用_bss与当前指令的下一条指令的“距离值”,而当base register是其他寄存器时,displacement就等于_bss自身的值。
而汇编成机器码之后,displacement的值已经由汇编器计算好了,CPU在执行的时候,%rip + displacement 和 %rbx + displacement不是一样的模式吗?
在搜索资料的时候,发现RIP相对寻址这个概念,这并不是一个汇编器的概念,而是CPU的,所以,既然把%rip + displacement这种寻址模式单独拿出来,那么还是会有差别的。
此外,在维基上看到的,RIP相对寻址是在x86-64加进去的:
http://wiki.osdev.org/X86-64_Instruction_Encoding#16-bit_addressing
RIP/EIP-relative addressing
Addressing in x86-64 can be relative to the current instruction pointer value. This is indicated with the RIP (64-bit) and EIP (32-bit) instruction pointer registers, which are not otherwise exposed to the program and may not exist physically. RIP-relative addressing allows object files to be location independent.
3. RIP相对寻址
那么为了进一步从CPU层面解释%rip + displacement和%rbx + displacement这两种寻址模式的区别,需要来看一下CPU如何解释机器代码。
下面是从《Intel 64 and IA-32 Architectures Software Developer's Manual》截取的几张图:

图3-1
这张图展示了一条机器码指令的结构,下面结合实际指令解释一下。
首先,在上面图1-1的例子中,查看一下两条lea指令所在的内存数据:
gdb$ x /14xb 0x1000241
0x1000241: 0x48 0x8d 0x35 0x30 0x3c 0x24 0x00 0x48
0x1000249: 0x8d 0xbb 0x78 0x3e 0x24 0x00
这里两条指令分别7个字节。
其中0x48是Prefixs,0x8d是lea指令的opcode,0x35和0xbb分别是两条指令的ModR/M,这里面没有SIB(下面解释),剩下的0x243c80和0x243e78就是两条指令的Displacement了。
Instruction Prefixs可以有很多种,上面的wiki链接也解释得很全了。这里的0x48是一种64位长模式特有的REX Prefix。对于REX Prefix的解释见下图3-2和3-3,其中高4位0100是固定的,低四位分别作为指令其他部分的扩展位。下面再进行解释。
那么上面的0x48,即为0100 1000,即W位为1,R X B 三个位都为0。
ModR/M 可以划分成3个field,高2位mod,中间3位reg,低3位r/m。例子中的0x35即为(00 110 101),还有0xbb即为(10 111 011),图3-4给出了一份助记表,可以找到0x35的坐标位(disp32,ESI),还有0xbb的坐标为([EBX]+disp32, EDI)。
看回例子中的“lea rsi,[rip+disp]” 和“lea rdi, [rbx]+disp”,rip作为base register和其他通用寄存器的区别在这里。但是,我也不知道该说这特不特殊了,全部是0和1之间的差别。
SIB在这两条指令中没有,答案可以从图3-4的NOTES.1中看到,当ModR/M中的mod域和R/M域为某些特定组合时,才存在SIB字节。
再看会刚刚的REX Prefix的R X B三个位,如何做其他部分的扩展在上面的wiki链接中挺全面。这里截了其中一个图作为解释性说明,见图3-5,当其中的B位为0时,ModR/M的r/m域是符合图3-4的,但是当B位为1时,r/m域选择的寄存器变成了从R8、R9...这些扩展寄存器中选择了。

图3-2

图3-3

图3-4

图3-5
从机器码理解RIP 相对寻址的更多相关文章
- RIP 相对寻址
知识共享许可协议本作品采用知识共享署名 4.0 国际许可协议进行许可.转载保留声明头部与原文链接https://luzeshu.com/blog/rip-relative-addressing 本博客 ...
- 第四次实验报告:使用Packet Tracer理解RIP路由协议
目录 1 实验目的 2 实验内容 3. 实验报告 3.1 建立网络拓扑结构 3.2 配置参数 3.3 测试网络连通性 3.4 理解RIP路由表建立和更新 4. 理解RIP消息传得慢 5. 拓展 1 实 ...
- 第四次作业:使用Packet Tracer理解RIP路由协议及ICMP协议
0 个人信息 张樱姿 201821121038 计算1812 1 实验目的 理解RIP路由表的建立与更新 感受RIP坏消息传得慢 2 实验内容 使用Packet Tracer,正确配置网络参数,使用命 ...
- X86/X64处理器体系结构及寻址模式
由8086/8088.x86.Pentium发展到core系列短短40多年间,处理器的时钟频率差点儿已接近极限.尽管如此,自从86年Intel推出386至今除了添加一些有关流媒体的指令如mmx/sse ...
- (转)示例化讲解RIP路由更新机制
目录(?)[+] 以下内容摘自最新上市的“四大金刚”图书之一<Cisco路由器配置与管理完全手册>(第二版)(其它三本分别为<Cisco交换机配置与管理完全手册>(第二 ...
- 有限等距性质RIP
参考博客:http://blog.csdn.net/jbb0523/article/details/44565647 压缩感知测量矩阵之有限等距性质(Restricted Isometry Prope ...
- RIP 实验
一.环境准备 1. 软件:GNS3 2. 路由:c7200 二.实验操作 实验要求: 1. 理解 RIP 协议的工作原理 2. 理解 RIPv1.RIPv2 的特性 3. 掌握 RIP 协议的基本配置 ...
- RIP实验
实验要求 1. 理解 RIP 协议的工作原理2. 理解 RIPv1.RIPv2 的特性3. 掌握 RIP 协议的基本配置方法4. 掌握 RIP 自动汇总和手动汇总的方法5. 掌握 RIP 配 ...
- 面试必问的 volatile,你了解多少?
前言 Java中volatile这个热门的关键字,在面试中经常会被提及,在各种技术交流群中也经常被讨论,但似乎讨论不出一个完美的结果,带着种种疑惑,准备从JVM.C++.汇编的角度重新梳理一遍. vo ...
随机推荐
- 非memory空间有地址分配
对于非memory空间有地址分配,是由于有寄存器配置,比如AHB.APB.一些外设.
- 创建虚拟机、安装centos系统,xshell连接虚拟机
创建虚拟机 文件--->新建虚拟机--->自定义最高级 选择虚拟机兼容性: workstation12.0:限制少,而且兼容的多 稍后安装操作系统 选择Linux系统 可选择centos7 ...
- PAT Basic 1035
1035 插入与归并 根据维基百科的定义: 插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列.每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置.如此迭代直到全部元素有序 ...
- JQuery中如何处理键盘事件
背景:比如在页面中,敲击回车键以后,实现登录功能,在之前的Winform开发时,也遇到过处理键盘事件的功能,比如游戏软件中,上下左右的移动等. 代码如下: $(document).keydown(fu ...
- WCF全局异常处理
在用wcf做为单纯的服务端的时候,发生错误是常有的事情,特别是在调用其他系统提供的接口的时候,发生的一些错误总是让人摸不着头脑,严重影响了错误的定位.做.net web开发的时候,我们可以在Globa ...
- Cookie测试的测试点
1.禁止使用Cookie:设置浏览器禁止使用Cookie,访问网页后,检查存放Cookie文件中未生成相关文件: 2.Cookie寻出路径:按照操作系统和浏览器对Cookie存放路径的设置,检查存放路 ...
- Linux快捷键列表
Linux快捷键列表 快捷键 功能描述 快捷键 功能描述 control+p 查询命令历史纪录的上一条命令 方向上键 查询命令历史纪录的上一条命令 control+n 查询命令历史纪录的下一条命令 方 ...
- Codeforces Round #402 (Div. 2) A+B+C+D
Codeforces Round #402 (Div. 2) A. Pupils Redistribution 模拟大法好.两个数列分别含有n个数x(1<=x<=5) .现在要求交换一些数 ...
- POJ 2092 Grandpa is Famous
Grandpa is Famous Time Limit: 2000MS Memory Limit: 30000K Total Submissions: 7153 Accepted: 3624 ...
- [luoguP1131] [ZJOI2007]时态同步(贪心)
传送门 显然是一棵树. 又显然一段一段地增加比较优. 我们可以dfs,并且尽量把每一个节点所有子树中所有节点的时间增加到一样. #include <vector> #include < ...