【问题标题】:assembly cltq and movslq difference汇编 cltq 和 movslq 的区别
【发布时间】:2016-10-11 03:22:15
【问题描述】:

Computer Systems A Programmer's Perspective(第 2 版)的第 3 章提到
cltq 等同于movslq %eax, %rax

他们为什么要创建一个新指令 (cltq) 而不是只使用 movslq %eax,%rax?这不是多余的吗?

【问题讨论】:

  • First of cltq 是 gnu 汇编器用于 x86 指令的名称 cdqe。这是一条两字节指令(1 字节 REX 前缀,1 字节操作码),该指令从 16 位 8086 开始使用。movslq 是更新的(在 386 中添加了 32 位扩展的基本操作码)并为等效功能占用 3 个字节。
  • @EOF,从技术上讲,movslq 甚至更新,在 32/16 位模式下使用 ARPL 的操作码。不过,它仍然是 3 个字节,包括 REX 前缀。 (而不是 movswq 或其他东西的 4 个字节。)在 Intel 语法中,它被称为 movsxd
  • 有人能解释一下movslq 的作用吗?

标签: assembly x86 x86-64 att sign-extension


【解决方案1】:

TL;DR:尽可能使用cltq(又名cdqe),因为它比完全等效的movslq %eax, %rax 短一个字节。这是一个非常小的优势(所以不要为了实现这一点而牺牲任何其他东西),但如果您想要签名扩展它,请选择 eax

这主要与编译器编写器相关(编译有符号整数循环计数器索引数组);诸如每次迭代都对循环计数器进行符号扩展之类的事情仅在编译器无法利用带符号溢出作为未定义行为来避免它时才会发生。人类程序员只需要决定什么是有符号的还是无符号的来保存指令。

(使用movsx / movslq 符号扩展到不同的寄存器可以避免延长32位值的依赖链,如果它在循环中更新,则相关。)


相关:在 RAX (cltq) 内或从 EAX 到 EDX:EAX (@ 987654343@),相当于movsx/movs?t?:What does cltq do in assembly?


历史

实际上,MOVSX 的 32->64 位形式(在 AT&T 语法中称为 movslq)是 AMD64 的新形式。 Intel 语法助记符实际上是MOVSXD。操作码是63 /r(所以它是 3 个字节,包括必要的 REX 前缀,而 8->64 或 16->64 MOVSX 是 4 个字节)。 AMD 重新利用了 ARPL 的操作码,这在 64 位模式下不存在。

要了解历史,请记住当前的 x86 并不是一次性设计的。首先是 16 位 8086,根本没有 MOVSZ/MOVZX,只有 CBW 和 CWD。然后 386 添加了 MOVS/ZX(以及更广泛的 CBW/CWD 版本,用于在 eax 或 edx 中进行符号扩展)。然后 AMD 将所有这些扩展到 64 位。

现有 MOVSX 操作码的 REX 版本仍然具有 8 位或 16 位源,但符号一直扩展到 64 位,而不是仅 32 位。操作数大小前缀允许您编码 movsbw,也就是 movsx r16, r/m8。 IDK 如果同时使用操作数大小前缀和 REX.W 会发生什么。或者,如果您在 MOVSX 的 16 位源格式中使用操作数大小的前缀,会发生什么情况。可能这只是编码 MOV 的一种昂贵方式,例如使用不带 REX 前缀的63 /r(英特尔的 insn 设置手册不建议这样做)。


cltq (aka CDQE) 是使用 REX.W 前缀扩展现有 cwtl (aka CWDE) 以将操作数大小提升到 64 位的明显方法。它的原始形式 cbtw(又名 CBW)在 8086 中,早于 MOVSX,并且是符号扩展任何东西的唯一合理方式。由于立即数>1 were a 186 feature 的移位,最不坏的其他选项似乎是 mov ah, al / mov cl, 7 / sar ah, cl 将符号位广播到所有位置。

另外,不要将 cwtlcwtd 混淆(aka CWD:将 ax 符号扩展为 dx:ax,例如为 idiv 设置)。

这里的 AT&T 助记符非常糟糕。 ld,真的吗?英特尔助记符的末尾都有 e 用于在 rax 中扩展的那些,而不是用于扩展到 rdx (部分)的那些。除了 CBW,当然这会将 al 扩展到 ax,因为即使 8086 也有 16 位寄存器,所以从不需要在 dl:al 中存储 16 位值。 idiv r/m8 使用 ax 作为源 reg,而不是 dl:al(并将结果放入 ah, al))。


裁员

是的,这是 x86 汇编语言中的众多冗余之一。例如sub eax,eaxxor eax,eax 相比,rax 为零。 (mov eax,0 并不是完全多余的,因为它不会影响标志。如果您将诸如此类的细微差异包括为冗余,甚至包括在不同执行端口上运行的指令,则有很多方法可以做一些事情。)。

如果我有机会修改 x86-64 ISA,我可能会给 MOVZX 和 MOVSX 单字节操作码(而不是 0F XX 两字节转义操作码),至少是 8 位源版本。所以movsx eax, byte [mem] 会和mov al, [mem] 一样紧凑。 (它们在 Intel CPU 上的性能已经相同:完全在加载端口中处理,没有 ALU uop)。大多数真实代码无法利用[u]int16_t 数组来提高缓存密度,所以我认为从word 到dword 或qword 的movs/zx 比较少见。或者也许有足够的宽字符代码来证明MOVZX r32/r64, r/m16 的较短操作码是合理的。为了腾出空间,我们可以完全放弃 CBW / CWDE / CDQE 操作码。我可能会保留 CWD / CDQ / CQO 作为 idiv 的有用设置,它没有等效的单指令。

实际上,可能具有更少的单字节操作码和更多的转义前缀会更有用(例如,常见的 SSE2 insn 可以是 2 个操作码字节 + ModRM,而不是通常的 3 或 4 个操作码字节)。在高性能循环中,指令解码的瓶颈较少。但是,如果 x86-64 机器代码与 32 位相差太大,我们需要额外的解码晶体管。现在可能没问题,因为功率限制已经使dark silicon 成为一件事,因为内核永远不需要在打开其 64 位解码器的同时打开其 32 位解码器。 AMD 在设计 AMD64 时并非如此。 (错误,在 32 位和 64 位运行的逻辑线程之间的超线程交替循环会阻止您完全关闭,如果它们是分开的。)

代替 CDQ,我们可以制作两个操作数移位指令,具有非破坏性目标,因此sar edx, eax, 31 将在 3 个字节中执行 CDQ。删除一字节 xchg-with-eax 操作码(0x90 xchg eax,eax NOP 除外)将为 sar, shr, shl 释放大量编码空间,而不需要 ModRM 的 Reg 字段作为额外的操作码位。当然,还要移除不影响标志的特殊情况 shift_count=0 以消除对 FLAGS 的输入依赖)。

(我也将setcc r/m8 更改为setcc r/m32。或者setcc r32/m8。(内存dst 无论如何都使用单独的ALU uop,因此它可以解码为setcc tmp32 并存储其中的低8)。它几乎总是用于对目的地进行异或归零,您必须在它与标志设置之间进行权衡。)

AMD 有机会(部分)使用 AMD64 做到这一点,但选择保守地共享尽可能多的指令解码晶体管。 (不能因此而责怪他们,但不幸的是,政治/经济环境导致 x86 在可预见的未来失去了放弃其一些遗留包袱的唯一机会。)这也意味着修改代码生成/分析软件的工作更少,但与可能使每个 x86-64 CPU 运行得更快并拥有更小的二进制文件相比,这是一次性成本和小土豆。


另请参阅 标签 wiki 以获取更多链接,包括 this old appendix from the NASM manual 记录何时引入每条指令的每种形式。

相关:MOVZX missing 32 bit register to 64 bit register

【讨论】:

  • 为什么这个答案如此受欢迎?对于巧妙地使用 SSE 或其他东西的答案,我通常会得到比这更少的支持。这只是一些指令集的奥秘,如果您考虑一下 x86 如何从 16 扩展到 32,然后扩展到 64,我认为其中的大部分内容都很明显。
  • 不问不说?我的意思是,如果你真的想要,我可以对你投反对票,让世界变得更直接。
  • @BeeOnRope:呵呵,我想更多的是在stackoverflow.com/questions/36327100/…stackoverflow.com/questions/35516878/…stackoverflow.com/a/34136751/224132 或其他一些我花了很长时间的其他答案上支持我的答案: P
  • 我猜你只是想知道使用哪一个,并将 TL:DR 放在顶部。它已经是粗体了...
  • @BulatM.:我的编辑是你所希望的吗?问题已经说它们是相同的。指令集演变的历史背景是这个问题值得回答的原因,IMO。另外,整理一下可能混淆的 CDQ 和 CDQE 命名。
猜你喜欢
  • 2021-04-14
  • 1970-01-01
  • 2014-01-21
  • 2020-03-03
  • 2017-01-21
  • 1970-01-01
相关资源
最近更新 更多