很难理解机器指令的执行

时间:2014-07-26 03:13:02

标签: cpu instructions

我正在阅读Randall Hyde撰写的“写出优秀代码:理解机器”一书,这是一篇非常清晰的文章,但在这里我完全坚持他对例如mov指令的解释。

他剖析了mov(srcReg,destMem)指令的步骤,如下所示:

1. Fetch the instruction's opcode from memory.
2. Update the EIP register with the address of the byte following the opcode.
3. Decode the instruction's opcode to see what instruction it specifies.
4. Fetch the displacement associated with the memory operand from the memory location immediately
following the opcode.
5. Update EIP to point at the first byte beyond the operand that follows the opcode.
6. If the mov instruction uses a complex addressing mode (for example, the indexed addressing mode),compute the effective address of the destination memory location.
7. Fetch the data from srcReg.
8. Store the fetched value into the destination memory location.

我在步骤4-6中丢失了。我的确切问题是:

第4步:为什么我需要这个位移,以后我将如何使用它以及为什么?

步骤5:据我所知,在步骤2中,EIP必须“指向”存储下一条要执行的指令的下一个字节。但我不明白为什么EIP需要超出操作数地址一个字节。我相信EIP只关心指令/操作码,而不是数据。

Step6:什么是完全有效的地址?还有其他类型的地址吗?

1 个答案:

答案 0 :(得分:2)

第4步:

某些操作码引用了与操作码位置相关的内存。例如,函数可能具有常量或静态数据。如果是这样,代码可以选择在函数开始之前(或在函数结束之后)放置它,并通过说“从早先的46个字节获取内存”来引用它。这就是位移 - 它是寄存器内容的偏移量(在本例中为EIP),用于引用与寄存器内容相关的数据。

第5步

操作码的操作数通常存储在操作码之后。所以你可能会有这样的记忆:a b ca是操作码,ba的操作数,c是下一个操作码。

如果您只将EIP移动到a的末尾(因此它引用b),那么在下一个指令周期中,计算机将假定b是下一个操作码执行。 b不应该是操作码;这是一个操作数。然而,计算机无法区分操作码和操作数之间的区别。它只是假设EIP指向的是指令并执行它。这就是为什么EIP也需要移过操作数的原因。

第6步

“有效”地址只是一个绝对地址(相对于内存的开始),而本书所指的“复杂”地址是相对于其他地址(通常是寄存器的内容)。

步骤4显示操作码可能不是指绝对存储器地址。它可以很容易地引用一个相对的。事实上,程序经常引用与某些寄存器相关的地址。例如,如果您在C中编写some_struct.data并为x86处理器编译它,它会将some_struct的地址加载到寄存器(例如,EAX)中,然后硬编码datasome_struct的基数偏移到操作数。因此,如果结构的开头和data元素的开头之间有5个字节的数据,则指令可能看起来像load [EAX + 5] -> EBX,这意味着“取EAX中的内容,添加5,获取来自该地址的数据并将其放入EBX“。

问题是,内存并不能真正理解这样的相对地址。它只能理解绝对的。因此,为了访问相对地址,处理器必须首先将该5添加到EAX中的任何地址以计算绝对地址。然后它可以将该地址发送到内存控制器并让它理解。

我使用过两种基本类型的相对地址(还有更多我没有)。

  • 寄存器相对:处理器获取寄存器的内容并将其用作存储器中的地址。根据操作码和处理器支持,它也可以向寄存器添加操作数。第4步是处理这种寻址,EIP是地址相对的寄存器。
  • 记忆相对:有时被称为“间接”。处理器以寄存器相对地址开始,然后自动获取该地址的数据并将其视为真实地址。
  • 维基百科在addressing modes页面上描述了许多其他寻址模式。

记忆相对需要一段时间来理解。假设您执行了内存相对加载,其中寄存器包含10且偏移量为5。处理器将它们一起添加(10 + 5 = 15)。然后,它将转到该地址(在这种情况下为15)并抓住那里的任何东西。如果地址15恰好包含值60,则60将被视为实际地址,处理器将加载地址60的内容。如果您熟悉带有指针的语言(例如C),则内存相对就像指向指针一样。