Assembly 基底与位移的差异
我在理解我遇到的两个说明时遇到一些问题。Assembly 基底与位移的差异,assembly,x86,intel,addressing-mode,Assembly,X86,Intel,Addressing Mode,我在理解我遇到的两个说明时遇到一些问题。 第一个是: imul eax,DWORD PTR [esi+ebx*4-0x4] 此指令是否意味着=>将括号之间计算的地址处的值乘以eax,并将其存储在同一寄存器(eax)中? 如果是这样的话,我们会这样计算括号中的地址吗 ebx*4 esi+操作1的结果 从结果中减去4 转到地址(结果)并获取其中的值 我发出解码的第二条指令是这条 jmp DWORD PTR [eax*4+0x80497e8] -eax*4是否等同于索引*刻度? -0x8
第一个是:
imul eax,DWORD PTR [esi+ebx*4-0x4]
此指令是否意味着=>将括号之间计算的地址处的值乘以eax,并将其存储在同一寄存器(eax)中?
如果是这样的话,我们会这样计算括号中的地址吗
jmp DWORD PTR [eax*4+0x80497e8]
-eax*4是否等同于索引*刻度?-0x80497e8是否为位移 所以要把地址放在括号里,这是我们应该遵循的顺序吗
当位移为负值时,这意味着什么 不要被术语所愚弄。“base”具有特定的技术含义,寻址模式的“base”组件不必是数组的开始。e、 g.
[esp+16+esi*4]
可以索引从esp+16
开始的本地数组,即使esp
是基寄存器
类似地,[esi+ebx*4-0x4]
最明显的解释是array[i-1]
,其中i
位于ebx中,esi
持有数组的起始地址。编译器将-1
折叠到寻址模式,而不是在另一个寄存器中计算ebx-1
并将其用作索引,这显然是一种优化
当位移为负值时,这意味着什么
它没有任何“意义”。硬件只进行二进制加法,并使用结果。由程序员(或编译器)使用寻址模式访问所需的字节
我的答案中有一些例子,说明了什么时候可以使用所有可能的寻址模式进行数组索引,可以使用指向数组的指针,也可以使用静态数组(因此可以将数组的起始地址硬编码为绝对位移)
在技术x86寻址模式术语中:
- 位移:地址的+常量部分,用扩展的
或disp8
补码编码。(在64位寻址模式中,disp32
符号扩展为64位)disp32
- 偏移量:esi+ebx*4-0x4计算的结果:相对于段基的偏移量。(在基址为0的普通平面内存模型中,偏移量=整个地址)
人们经常使用“偏移量”来描述位移,通常不会产生混淆,因为从上下文中可以清楚地看出,他们谈论的是恒定偏移量(使用英语单词offset的意思不是x86
),但我喜欢使用“偏移量”来描述位移seg:off
- 基址:寻址模式的非索引寄存器组件(如果有)。(改为“无基址寄存器”的编码意味着存在一个
,您可以将其视为一个基址。它意味着DS段。) 这包括只有索引而没有基址寄存器的情况:disp32
只能编码为[esi*4]
[dword 0+esi*4]
是,
eax*=内存源操作数
是的,你的地址计算是正确的。基+缩放索引+有符号位移,生成虚拟地址1
“转到地址(结果)并获取其中的值”是一种奇怪的描述方式。“go to”通常意味着控制传输,将字节作为代码获取。但事实并非如此,这只是来自该地址的数据加载,完全由硬件处理
现代x86 CPU(例如Intel Skylake)将imul eax、[esi+ebx*4-4]
解码为两个UOP:一个imul ALU操作和一个加载。ALU操作必须等待加载结果。(有趣的事实:对于大多数管道,这两个微操作实际上是微融合到一个uop中的,除了在无序调度程序中。有关更多信息,请参阅。)
当load uop运行时,地址生成单元(AGU)获得2个寄存器输入、索引比例因子(左移2)和即时位移(-4
)。AGU中的shift和add硬件计算加载地址
加载执行单元内的下一步是使用该地址从L1d缓存加载(基本上内置了第一级L1dTLB虚拟->物理缓存。L1d是虚拟索引的,因此TLB查找可以与从L1d缓存中获取8个标记+数据集并行进行)。假设L1dTLB和L1d缓存中有命中,负载执行单元在5个周期后收到负载结果
加载结果作为源操作数转发给ALU执行单元。ALU不关心它是imul eax、ebx还是内存源操作数;只要两个输入操作数都准备好,乘法uop就被分派到ALU
是,
eax*4
是缩放索引
是,0x80497e8
是disp32位移。在这种情况下,寻址模式的位移分量可能被用作静态跳转表的地址。您可以将其视为此寻址模式的基础
跳转到那个地址
否,从该地址加载新的EIP值。这对我来说是个挑战
imul eax,DWORD PTR [esi+ebx*4-0x4]
jmp DWORD PTR [eax*4+0x80497e8]
lea eax, [eax*4+0x80497e8] ; address calc
jmp eax ; jump to code at that address