以下代码中的
xchg
指令如何工作?已知 arrayD 是一个 1,2,3 的 DWORD 数组。
mov eax, arrayD ; eax=1
xchg eax, [arrayD+4] ; eax=2 arrayD=2,1,3
为什么
xchg
后面不是数组1,1,3?
xchg
工作原理就像英特尔文档所说的那样。
我认为第二行的评论是错误的。 应该是
eax=2
,arrayD = 1,1,3
。所以你是对的,你应该给你的老师发电子邮件说你认为你发现了一个错误,除非你在笔记中遗漏了一些东西。
xchg
只存储一个元素,它无法神奇地及时回溯以了解 eax 中的值来自哪里,也无法用一条 xchg
指令交换两个内存位置。
在一条指令中将
1,2
交换为 2,1
的唯一方法是 64 位循环,如 rol qword ptr [arrayD], 32
(仅限 x86-64)。
顺便说一句,如果您关心性能,请不要将
xchg
与内存操作数一起使用。它在 386 及更高版本上有一个隐式 lock
前缀,因此它是一个完整的内存屏障,甚至除了等待存储缓冲区耗尽之外,在 Haswell/Skylake 上也需要大约 20 个 CPU 周期(http://agner. org/optimize/ 和 https://uops.info/)。当然,多个指令可以同时运行,但 xchg mem,reg
是 8 个微指令,而单独加载 + 存储总共有 2 个微指令。 xchg
不会停止管道,但内存屏障会造成很大影响(阻止稍后的加载提前启动以及等待较早的加载和存储完全完成)。为了使其原子化,CPU 也要做很多工作。
相关:
xchg
才对这种情况有用。或者在 386 之前的 CPU 上,其中 xchg
并不意味着 lock
。xchg reg,reg
,没有内存屏障)mfence
的指令级并行性与 lock
ed 操作