TL:DR:无论如何,您都可以在解码期间找到指令的结尾,并设置下一条指令的解码。 CPU相对于当前指令的end进行相对寻址是很正常的,尽管有些CPU会做出不同的选择,例如相对于下一条指令的终止(对于ARM PC相对内存寻址)。
x86机器代码设计在80年代末与8086紧密相连,除了在扩展ISA时重新设计的东西(例如32/64位ModRM + SIB寻址模式)。>
原始8086顺序解码的指令字节(不必一次解码整个指令,并且前缀字节数或总指令长度没有上限。
I 思考
8086避免了[[ever需要保存指令的起始地址,]],即使是例外情况也是如此。例如,在现代x86上,Does Program Counter hold current address or the address of the next instruction?(除法异常)会推送错误指令的地址。但是#DE
。8086甚至有一个“ bug”(或已记录的设计缺陷),其中在执行on 8086 the exception frame has the address of the next instruction期间到达的中断(例如)将最终前缀的地址推送为异常返回地址,从而使段覆盖cs rep movsb
-string指令在启用中断的情况下基本上不可用。 (因为执行将在没有rep
或没有段覆盖的情况下恢复执行,以您为先)。参见rep
和注释。当8086完成对x86 Program Counter abstracted from microarchitecture?指令的解码时,它不知道从哪里开始。它唯一的参考点是call
指令的结尾。
call
操作码的地址(在任何前缀之后)作为锚点,但这可能需要额外的加法器或额外的硬件来单独记录。获取/解码已经必须在解码过程中找到指令的末尾(同时确定它是E8 call
或call
),所以指令的末尾/下一条指令的地址已经在内部可用。 jmp
甚至必须将该值作为返回地址推入堆栈。流水线RISC或完全未流水线的CPU,也将使用该下一条指令地址从内存或I-cache中获取下一条指令。但是实际上,8086预取与异步到一个小的预取缓冲区中。机器代码格式是在纸上设计的,通常是在实现设计之前设计的,因此,使该内容与指令末尾有关的常见原因可能是架构师考虑的。
[这是许多ISA相对于指令结尾进行分支的常见设计选择。
first
代,理解它有助于解释一些机器代码设计决策。 (例如,为什么x86在单字节call
上花费8个操作码:因为8086没有xchg [e/r]ax, reg
或2运算符movsx
,并且需要或希望使用AX来处理很多东西。此外,代码大小也是性能的主要瓶颈。)现代x86仅跟踪每个指令的地址,并且在解码imul
时可以使用该地址。没有大碍。 call rel32