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)
这样看起来对吗?
感谢您的帮助,
克莱曼
这不可能是正确的。
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
如果你是 "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,用于多处理器同步,这使得这段代码
比上面的第一个解决方案慢很多。
我刚开始接触 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)
这样看起来对吗?
感谢您的帮助, 克莱曼
这不可能是正确的。
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
如果你是 "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,用于多处理器同步,这使得这段代码 比上面的第一个解决方案慢很多。