use*_*897 2 x86 assembly addressing-mode
为了提供一些背景知识,我想研究x86指令是如何手动编码/解码的。我遇到了ModR/Mand SIB字节,似乎了解x86寻址模式对于理解指令编码方案至关重要。
因此,我在Google搜索了x86寻址模式。搜索返回的大多数博客/视频都是8086处理器的寻址模式。通过其中的一些,不同的寻址模式是寄存器,直接,间接,索引,基于等。但是,在引用这些寻址方式时,博客使用的名称不一致。多个不同的源使用多种不同的寻址模式。此处的英特尔手册中甚至没有提到这些不同的术语。例如,我似乎无法在Intel手册中找到任何称为“直接”或“间接”的寻址模式。另外,Mod在比特ModRM字节是一个2比特字段,这使我不知道是否超过4种的寻址方式是可能的。
我的问题是,诸如直接寻址模式之类的术语是间接寻址模式的旧术语,这些术语不再在英特尔手册中使用,而是由公众使用。如果存在技术上确实存在的术语,则可以在手册中找到它们的引用。
大多数形式的x86寻址模式并没有真正的正式名称。[base + index*scale + disp8/disp32]除了64位相对RIP寻址之外,它们都具有形式(或该形式的任何1或2个组件的子集)。 引用存储位置的内容。(x86寻址模式)。
英特尔确实在卷1的第3.7.5节中正式命名了寻址模式的那些组成部分。它们还使用了寄存器,立即数和内存,但是通常对不同形式的寻址模式没什么大不了的。
ModRM字节中的Mod位是2位字段,这使我想知道是否可以使用4种以上的寻址模式。
Mod使用disp0 / 8/32选择Register vs.Memory。有用于更多模式的“转义”代码
[rbp]相反,没有位移的模式意味着存在一个没有基础的disp32。(这就是为什么[rbp+0]在反汇编中看到的原因:最好的编码[rbp]是base = rbp,disp8为0。(请注意,[rbp]当它是帧指针时,它没有用。)[rsp],而不是减少了用途[rsp+rsp]。)用英语写汇编语言时,很自然地使用具有明显含义的术语,包括您提到的某些术语。例如,英特尔的优化手册说(我强调):
2.3.2.4 Micro-op队列和循环流检测器(LSD)
...(具有索引寻址模式的微融合微件在SnB的IDQ中未分层)
...对于以索引寻址为主的代码(通常在数组处理中发生),使用基址(或基址+位移)寻址的重新编码算法有时可以通过保持加载加操作和存储指令融合来提高性能。
索引寻址模式包括使用的任何组合,idx*scale无论它是与基本reg还是与disp32一起使用,或两者都使用。(idx本身并不是encodeable; [rax*1]实际编码为disp32+idx*1用disp32=0。)在某些时候,他们说的或类似的“与索引任何寻址模式”,否则可能并不清楚他们的意思是什么。当然,使用性能计数器进行测试可以验证解释。
但是他们并不会过度地为事物起名字。当没有明显的英语短语时,他们可以贴在某物上,然后写道(仍在Sandybridge部分中):
常见的加载延迟为五个周期。当使用简单的寻址模式(基数加偏移量小于2048)时,加载延迟可以为四个周期。
在表2-19中,它们有两列,一列用于Base + Offset > 2048;或
Base + Index [+ Offset],另一列用于Base + Offset < 2048具有低1个周期的延迟(256b AVX负载除外)。(有趣的是,[rdi+8]延迟时间比少1分[rdi-8]。)
(从技术上讲,他们可能应该说“位移”,因为整个寻址模式在x86术语中形成一个偏移量或有效地址,当添加到段基时,它会形成一个线性地址。但是“偏移量”也用于描述立即常数。非x86通用术语中的寻址模式的一部分。幸运的是,现在这些天通常不必考虑x86分段。)
在第1卷手册中,英特尔确实使用了您描述的某些术语。他们将仅具有位移分量的寻址模式描述为“直接”(某种)和[reg]“间接”,因为在谈论指令集及其支持的寻址模式时,确实会使用这些术语。
以下寻址模式建议用于地址组件的常见组合。
移位 ?单独的位移表示对操作数的 直接(未计算)偏移。因为位移是在指令中编码的,所以这种地址形式有时称为绝对地址或静态地址。它通常用于访问静态分配的标量操作数。
基地?单独的基数表示操作数的间接偏移量。...
- (索引?比例)+位移?此地址模式提供了一种索引到静态数组的有效方法。
- 基础+指数+位移...
- 基数+(索引?比例)+位移?当数组的元素大小为2、4或8个字节时,将所有寻址组件一起使用可以对二维数组进行有效索引。
但是正如您所看到的,它们并没有为更复杂的表单命名。
但是,它们的确可以区分立即数操作,寄存器操作数和内存操作数。(3.7运营商地址)。但是,它们通常在使用寄存器编码的r / m32操作数与必须是寄存器的其他操作数之间几乎没有区别。
分支机构也可以采用直接还是间接。有点像谈论寻址模式,以达到下一个将要运行的代码字节。
6.3.7 64位模式下的分支功能
...
地址大小会影响用于JCXZ和LOOP的RCX的大小;它们还会影响内存间接分支的地址计算。默认情况下,此类地址为64位。但可以使用地址大小前缀将其覆盖为32位。
间接内存是jmp [rax],其中RIP的最终值来自内存,而寄存器间接分支jmp rax设置RIP = RAX。x86没有用于加载/存储的内存间接寻址模式;采取分支后的代码获取在术语中引入了额外的间接级别。(有点)。
第2卷的手动入门jmp确实讨论了间接跳跃,相对跳跃或绝对跳跃。(尽管请注意,x86没有绝对直接近跳转(为此在寄存器中放入地址),只有绝对远地址由立即指针(ptr16:16或ptr16:32)或间接与内存位置一起指定。)
当描述接近间接跳转jmp r/m32(或64)时,他们说“在GP寄存器或内存中间接指定的绝对偏移量”。(“绝对偏移”是相对于CS段基础的)。
分段使x86寻址更难以讨论,尤其是在比较可以显式包含段的特殊寻址模式与不包含特定段的特殊寻址模式时。
记住x86寻址模式可以根据一般情况的子集进行操作要容易得多,而不是用诸如Indexed,Based之类的名称分别存储所有不同的可能性。
您会在类似https://www.tutorialspoint.com/microprocessor/microprocessor_8086_addressing_modes.htm或http://www.geeksforgeeks.org/addressing-modes/的教程中看到这种东西,这些东西对分类寻址模式大有帮助。后者甚至有一个测验,要求您将C语句与某些寻址模式名称匹配。
使用不太灵活的16位寻址模式,您几乎可以尝试命名它们,而“基数索引”和“索引索引”确实为您提供了不同的寄存器选择。但是,当您进行编程时,您真正需要记住的是,这是您选择的任何子集[bx|bp] + [di|si] + disp0/8/16。这就是di/ si(dst / src索引)的方式,也许bx/bp还有他们的名字。
这样的术语在比较不同ISA的功能时可能很有用。例如,维基百科说像PDP-8这样的旧ISA大量使用了间接存储,因为它们的寄存器很少,并且寄存器的寻址范围只有8位。
维基百科还说:
请注意,没有一种普遍接受的命名各种寻址模式的方法。
在模式命名上花很多钱是没有道理的。如果要写东西,请确保清楚您的意思,而不必依赖某些术语的特定技术含义。例如,如果您说“索引寻址模式”,请确保读者从上下文中知道您是否包括在内base+index*scale。
我想知道是否某些命名模式的起源是早于8086的8位微控制器。您可能想在https://retrocomputing.stackexchange.com/上进行询问。我对使用固定的一字节指令的8位CPU可用的寻址模式了解不多。