【问题标题】:How does xchg work in Intel Assembly Languagexchg 如何在英特尔汇编语言中工作
【发布时间】:2018-10-10 15:45:52
【问题描述】:

有人能解释一下 xchg 在这段代码中是如何工作的吗?假设 arrayD 是 1,2,3 的 DWORD 数组。

mov eax, arrayD ; eax=1
xchg eax, [arrayD+4]; eax=2 arrayD=2,1,3

为什么数组 1,1,3 不在 xchg 之后?

【问题讨论】:

  • 为什么你认为数组末尾的值是 2,1,3?
  • mov eax, arrayD 不会将 eax 设置为 1。它加载arrayD 的地址。你想要的是mov eax, [arrayD]。编辑:误读初始状态。
  • @Jester 这取决于汇编程序。一些汇编程序将arrayD[arrayD] 视为相同。
  • @interjay 是的。 OP 应该有指定的汇编器。
  • 我总是建议即使在 MASM 中也使用方括号,以便在读取源代码时轻松查看内存访问,并与非符号内存引用保持一致,例如 mov eax,[ebx]。 MASM 将忽略符号名称周围的[],因此您可以在这种情况下编写mov eax,[arrayD]。 ...(大约 +4 .. 你知道内存可以通过单字节寻址,所以 32 位值占用内存中的 4 个字节 = 该数组的第一个元素占用地址 arrayD+0arrayD+1arrayD+2arrayD+3。第二个元素从地址arrayD+4开始(最多占用内存+7)

标签: assembly x86


【解决方案1】:

xchg 工作 like Intel's documentation says

我认为第 2 行的评论是错误的。 应该是eax=2arrayD = 1,1,3所以你是对的,你应该给你的老师发邮件说你认为你发现了一个错误,除非你在笔记中遗漏了什么。

xchg 只存储一个元素,它不能神奇地及时回溯以知道 eax 中的值来自哪里并用一条xchg 指令交换两个内存位置。

在一条指令中将 1,2 交换为 2,1 的唯一方法是 64 位循环,例如 rol qword ptr [arrayD], 32(仅限 x86-64)。


顺便说一句,如果您关心性能,请不要将xchg 与内存操作数一起使用。它有一个隐含的lock 前缀,因此它是一个完整的内存屏障,在 Haswell/Skylake (http://agner.org/optimize/) 上需要大约 20 个 CPU 周期。当然,多个指令可以同时运行,但xchg mem,reg 是 8 微指令,而单独的加载 + 存储总共是 2。 xchg 不会停止流水线,但内存屏障会造成很大的伤害,而且 CPU 需要做很多工作才能使其成为原子。

相关:

【讨论】:

    猜你喜欢
    • 2012-10-22
    • 2011-04-29
    • 2023-03-17
    • 2021-02-06
    • 2016-07-13
    • 2011-09-21
    • 2011-02-14
    • 1970-01-01
    相关资源
    最近更新 更多