【问题标题】:Why cannot do mov [eax], [ebx] [duplicate]为什么不能做 mov [eax], [ebx] [重复]
【发布时间】:2019-06-26 04:59:43
【问题描述】:

我可以这样做:

mov eax, ebx

还有这个:

mov [eax], ebx

甚至这个:

mov eax, [ebx]

但不是这个(错误 C2415):

mov [eax], [ebx]

只是 wtf... 为什么? 和 *ptr1 = *ptr2 一样,为什么我可以将一个寄存器复制到另一个寄存器,通过寄存器中的地址将值复制到另一个寄存器或将寄存器的值复制到另一个寄存器中存储的地址...

但它不能将一个地址上的值复制到另一个地址。为什么?

【问题讨论】:

  • x86 处理器不支持 mov 的两个内存操作数。请查阅指令集参考和/或基本架构手册。要实现您想要的,您需要通过注册。
  • 因为CPU不支持
  • 这是*ptr1 = *ptr2 编译为:godbolt.org/z/6xQhcR
  • 不要把汇编当作“编程语言”,它更像是“CPU指令的名称”,即CPU供应商在硬件中实现的东西,在汇编器中作为指令可用。有一些例外,比如有一些辅助宏或“伪指令”(一个伪指令被转置为多个本机指令),但通常映射是 1:1,即源代码文本中的一条指令映射到一条识别的硬件指令通过 CPU。如果 CPU 供应商不提供mov [eax],[ebx],那么汇编器就无能为力了(至少它会报告错误,有些不会;))。

标签: assembly x86


【解决方案1】:

你不能做 mov [eax], [ebx] 因为这意味着一个机器指令可以让你指定两个内存操作数。 x86 指令集主要围绕机器指令设计,允许您指定一个寄存器和一个内存操作数,因为这非常有用,并且它不会影响获取寄存器然后分步放入内存的操作的性能。

与所有复杂的指令集架构一样,有一些原则(例如,上述),但也有一些例外,用于其他目的。

您可能对有效的 MOVB/MOVW/MOVD 指令感兴趣(分别):

 MOV byte[edi], byte[esi]; add edi,1; add esi,1
 MOV word[edi], word[esi]; add edi,2; add esi,2
 MOV dword[edi], dword[esi]; add edi,4, add esi,4

(不,您不能选择寄存器;这些是硬连线以使用 ESI 和 EDI)。就其本身而言,这并不是很有趣(除了完全按照您的意愿行事:),但可以使用 REP 前缀重复它以构造块移动。并且芯片设计人员非常努力地使这种块移动运行得非常快。

[对于 64 位 x86,有一个对 qwords 进行操作的 MOVQ]。

如果您要编写汇编代码,在编写大量代码之前仔细阅读指令集说明是值得的。

【讨论】:

    【解决方案2】:

    mov [eax], [ebx] 表示“将ebx 指向的内存位置的内容移动到eax 指向的内存位置。这是内存到内存的移动,英特尔不支持。

    【讨论】:

    • 请注意,虽然不支持一般的内存到内存的移动,但支持一些特殊情况(例如push m32)。
    【解决方案3】:

    mov 指令可接受的操作数显示为here

    mov [eax], [ebx] 正在尝试将一个内存位置(从ebx 寄存器中的值取消引用)移动到eax 中引用的内存位置。 mov 没有将内存位置作为源和目标的操作码,但是有用于将内存位置移动到寄存器中的操作码,将寄存器移动到内存位置,立即数到寄存器,立即数到内存位置,或 16 位 GPR 到段寄存器中。

    【讨论】:

      猜你喜欢
      • 2013-01-31
      • 2014-10-28
      • 2012-05-21
      • 1970-01-01
      • 1970-01-01
      • 2016-02-09
      • 2019-03-30
      • 2017-05-05
      • 1970-01-01
      相关资源
      最近更新 更多