x86:使用内存/交换值?

x86: using memory / swapping values?

我刚开始接触 x86 系统 class,有几个问题:

1) 假设我引用了一段内存:

(%eax)

圆括号表示我正在访问内存,%eax 表示我想访问那个内存中的特定地址。因此,如果寄存器 %eax 存储 0x104(%eax) 将 return 存储在内存位置 0x104 的任何内容。这是正确的吗?

2) 假设我想交换存储在 (%eax)(%ebx) 的值。这是我的 尝试:

//store values in registers
movl (%eax) eax
movl (%ebx) ebx

//store values in opposite registers from where they came originally
movl ebx (%eax)
movl eax (%ebx)

这样看起来对吗?

感谢您的帮助, 克莱曼

这不可能是正确的。

EAXEBX 开始包含内存位置。然后取消引用内存,将实际值移动到同名的寄存器中:

 MOVL (%EAX), EAX
 MOVL (%EBX), EBX

EAXEBX 不再包含内存地址;它们现在包含来自这些地址的内容。当您下次执行此操作时:

 MOVL EBX, (%EAX)
 MOVL EAX, (%EBX)

您正在将这些内存位置的值存储到恰好等于那些值的任何内存位置,这几乎肯定不是您想要的,并且几乎可以保证不会交换这些值。

如果内存位置本身存储内存位置的值,则此 工作的唯一方法,这没有多大意义。

1) 是的,如果您正在阅读一个值。如果您正在写入一个值,则位置 0x104 中的内容无关紧要,它将被覆盖。

2) 不。您的代码首先销毁目标内存位置中的值, 通过存储内存位置的地址内存位置。

[我在阅读您的汇编符号时有些困惑:在许多汇编器中,人们只写 "eax",而不是“%eax”;这些不是不同的寄存器。我不知道你写那个是因为你的汇编程序要求你这样做 [[你使用的是哪个汇编程序?]] 或者这只是一个错字。在下文中,我总是使用裸寄存器名称,在 MASM 汇编语法]

要交换两个位置,您几乎需要原来的两个和 临时存储原始值的地方:

  mov   ecx, [eax]    ; fetch memory specified by address in eax
  mov   edx, [ebx]    ; fetch memory specified by address in ebx
  mov   [eax], edx    ; put 2nd value where 1st used to be
  mov   [ebx], ecx    ; put 1st value where 2nd used to be

如果你是 "swapping" 寄存器(例如 eax 和 ebx),你可以只用一个临时的:

  mov   ecx, eax      ; save 1st value in temp location ecx
  mov   eax, ebx      ; set 1st value to 2nd location
  mov   ebx, ecx      ; set 2nd value to copy of 1st value

x86 有一个特殊的 "xchg" 指令,这使得这很容易:

  xchg  eax, ebx      ; exchange  eax with ebx

你可以在内存位置使用它:

  mov   ecx, [eax]    ; save 1st value in temporary ecx
  xchg  ecx, [ebx]    ; swap with 2nd value
  mov   [eax], ecx    ; set 2nd value to swapped temp

不幸的是,与内存位置一起使用的 xchg 包含一个空闲的隐式 LOCK,用于多处理器同步,这使得这段代码 比上面的第一个解决方案慢很多。