汇编中的间接寻址(x86)



这是间接寻址的格式:

example: 
| Base | + Index * Scale | + Discplacement  |
|------|-----------------|------------------|
| EAX  |    EBX  *   2   |8-Bit Displacement|

但有一些事情我还不明白:

  • 如果我们在EAX中有一个地址并添加EBX*2,这会取位于EBX*2中的地址/值并将其添加到EAX中的值/地址吗?

  • 位移究竟是什么,为什么可能有8位、32位或无位移,而不是4位或2位位移?

  • 如果我们在EAX寄存器中有每个4字节大的值,我们将乘以EAX*4,但为什么要乘以字节值(我知道每个单元有1个字节(。这是否意味着它会自动将字节转换为位?

完整的公式应该是"address = (base + index << scale + displacement) & mask";。

注1:";比例尺;是移位计数,没有乘法运算。它只是为了方便人类而被描述为乘法。

注2:";掩模";用于表示对目标大小的包装/截断。例如,如果base + index << scale + displacement计算为0x0000000212345678,但CPU需要32位地址,则掩码将为0x00000000FFFFFFFF,实际结果将为0x12345678。

如果我们在EAX中有一个地址并添加EBX*2,这会取位于EBX*2中的地址/值并将其添加到EAX中的值/地址吗?

是。例如,如果EAX=3并且EBX=10,则EAX+EBX*2将是23。

位移究竟是什么,为什么可能有8位、32位或无位移,而不是4位或2位位移?

位移只是一个加在其余部分上的数字。对于内存访问;它经常用于访问结构字段(例如"结构的地址+结构中第n个字段的偏移量"(和堆栈位置(例如"堆栈顶部-从堆栈顶部偏移量"(。

CPU主要只是读取一系列数字;然后需要能够对数字进行解码,以弄清楚指令是什么以及它的操作数是什么(并且一旦对数字进行了解码,它就执行相应的指令(。更多的可能性使得解码更加困难,这需要通过有用性来证明。2位和4位位移可以简单地四舍五入到8位,这使得很难证明解码的额外复杂性。

只有2位(ModRM字节中的模式字段(可以用信号表示寄存器与没有disp的内存、有8位disp的存储器或有32位disp内存之间的关系。如果有更多的选择,就会从其他地方拿走更多的位;disp是一个简单的二进制值(进行符号扩展(,它本身不使用可变长度编码。(幸运的是,否则指令长度解码将不得不查看它,而不仅仅是前缀+操作码+ModRM字节。(

如果我们的值每个都是4字节大-在EAX寄存器中,我们将乘以EAX*4,但为什么要乘以字节值(我知道每个单元都有1个字节(。这是否意味着它会自动将字节转换为位?

;EAX*4";实际上是";EAX<lt;2〃;。小的移位计数是非常常见的(例如shl eax,cl(;移位计数太大";(例如,在32位计算中大于32(与目的地大小的掩码相结合使其毫无意义。例如,考虑一个虚构的";address=(EAX<<32(&0xFFFFFFFF";(这是毫无意义的,因为它可以用"address=0"代替(。

本质上,对于32位地址计算,从0到31的移位计数可能有用,而较小的移位计数(从0到3(最有用。在这一点上,我们可以回到";更多的可能性使得解码更加困难,并且这需要通过有用性来证明;理解为什么80x86只支持从0到3的移位计数(或乘法器1、2、4和8(;即使其它移位计数(例如"EAX<<4"或"EAX*16"(偶尔可能有用。

2、4和8是数组的常见元素大小,因此这种2位移位计数可以对双字数组进行索引,例如使用保存元素编号而不是字节偏移的寄存器。

最新更新