Assembly x86:使用内存/交换值?

Assembly x86:使用内存/交换值?,assembly,x86,Assembly,X86,我刚刚进入x86系统课程,有几个问题: 1) 假设我引用了一段内存: (%eax) 括号表示我正在访问内存,%eax表示我要访问内存中的特定地址。因此,如果寄存器%eax存储0x104,(%eax)将返回存储在内存位置0x104的任何内容。这是正确的吗 2) 假设我想交换存储在(%eax)和(%ebx)的值。这是我的 尝试: //store values in registers movl (%eax) eax movl (%ebx) ebx //store values in opposi

我刚刚进入x86系统课程,有几个问题:

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

(%eax)
括号表示我正在访问内存,
%eax
表示我要访问内存中的特定地址。因此,如果寄存器
%eax
存储
0x104
(%eax)
将返回存储在内存位置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)
这个看起来对吗

谢谢你的帮助,
b不可能是正确的外行

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

 MOVL (%EAX), EAX
 MOVL (%EBX), EBX
EAX
EBX
不再包含内存地址;它们现在包含这些地址的内容。下次执行此操作时:

 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
如果您正在“交换”寄存器(例如,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包含一个空闲的隐式锁,用于多处理器同步,这使得这段代码
比上面的第一个解决方案慢得多。

1)是的。2) 没有。(甚至忽略掉掉掉的逗号。)我对第二部分有点困惑。前两条语句似乎就是我想要做的(将内存中的值存储到寄存器中)。具体来说,我不确定您在这里的意思:“您正在将这些内存位置的值存储到恰好等于这些值的任何内存位置”…谢谢@门外汉:也许可以用更好的措辞。这里要理解的关键是%EAX和EAX是同一个寄存器。因此,例如,如果%EAX的原始值是0x104,并且地址0x104处的RAM中的数据是0x333,则执行
movl EAX,(%EAX)
将值0x333存储在RAM地址0x333@slebetman嗯,那么如果EAX==0x104,(%EAX)是M[0x104]==0x333,那么为什么movleax,(%EAX)不将值0x104移动到RAM地址0x104中呢?再次感谢!因为%EAX在您将其值复制到自身后不再是0x104:
movl(%EAX),EAX
。也许我应该这么说:)我认为最初的海报使用的是AT&T语法,它以%作为寄存器名的前缀,并颠倒操作数的顺序。Aha。这就是汇编程序的问题所在;每个人都发明了自己的语法。“%”是可选的,这让人很困惑。我认为我的答案仍然有效,如果OP理解我的语法与他不同,并且操作数顺序颠倒:-}在AT&t语法中,%不是可选的,但逗号也不是可选的。AT&T语法还使用
(%eax)
和MOVL,其中MASM使用
[eax]
和MOV DWORD PTR。(MASM将
mov-eax,(eax)
解释为
mov-eax,eax
)@RossRidge:唉,你说得对。我见过太多的语法,有时我会迷失方向。令我惊讶的是,我深夜的大脑毫无疑问地将OP的(…)读作“索引依据”,现在我明白了为什么AT&T语法需要间接寄存器上的%。受此影响,我在回答中为[…]写了(…)。编辑。语法检查很好。助记符是否从
xchg
缩短为
xch