何时以及为什么我们签署扩展和使用干熄焦与MUL / DIV? [英] When and why do we sign extend and use cdq with mul/div?

查看:127
本文介绍了何时以及为什么我们签署扩展和使用干熄焦与MUL / DIV?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我做了一个测试todayand我不明白涉及双转换为四字只是​​时间问题。

这让我思考,为什么/我们什么时候签延长乘除?此外,当我们使用说明像干熄焦?


解决方案

你可以从一个insn参考手册(链接在的 86 标签的wiki)标签的86显示问题:


  • 单操作数 MUL / IMUL EDX:EAX = EAX * SRC

  • 双操作数 IMUL DST * = SRC



  • DIV / IDIV :分裂 EDX:EAX 由src。在商 EAX ,其余的在 EDX 。有没有 DIV / IDIV 的形式,忽略 EDX 中输入。

  • 干熄焦登录扩展 EAX EDX:EAX ,即广播 EAX 的符号位为 EDX 的每一位。不要与 cdqe ,64位指令,可以做混淆 MOVSX RAX,EAX 用较少的insn字节。

    最初(8086),只是有 CBW AX = SIGN_EXTEND(人))和 CWD DX:AX = SIGN_EXTEND(AX))。 86到32位和64位扩展所做的助记符有些模棱两可(但要记住,不是 CBW 其他的内,EAX版本总是以结束 Ë的延伸)。没有DL = sign_bit(人),因为8位MUL和DIV是特殊的,并使用而不是 DL指示:人



由于输入 [I] MUL 是单寄存器,你永远需要之前做 EDX 什么乘法。

如果您输入的签署,您符号扩展它来填充你使用作为输入到乘法例如寄存器与 MOVSX CWDE EAX = SIGN_EXTEND(AX) )。如果输入是无符号,你零扩展。 (所不同的是,如果你只需要乘法结果的低16位,例如,<一个href=\"http://stackoverflow.com/questions/34377711/which-2s-complement-integer-operations-can-be-used-without-zeroing-high-bits-in/34377712#34377712\">it如果任一方高16位或两个输入包含垃圾的无关紧要。)


对于一个鸿沟,你总是需要到零或符号扩展EAX到EDX。零延伸是一样的只是无条件零EDX,所以有它没有什么特别的指令。刚 XOR EDX,EDX

干熄焦的存在,因为它比 MOV EDX,EAX / 特区EDX短很多31 播出EAX的符号位在EDX每一位。此外,随着移动计数> 1是不存在的,直到286,所以在8086,你需要一个循环,如果 CWD 不存在(<$的16位版本C $ C>干熄焦)。


在64位模式,符号和零扩展的32位值64是常见的。该ABI允许在64位寄存器,保持32位值的高32位的垃圾,所以如果你的函数只应该看看 EDI 的低32位,你不能只需使用 [阵列+ RDI] 索引数组。

所以你看到很多的 MOVSX RDI,EDI (符号扩展),或 MOV EAX,EDI (零扩展,是的这是更有效地使用不同的目标寄存器,因为英特尔MOV淘汰不符合 MOV一样,同样

工作

I had a test todayand the only question I didn't understand involved converting a doubleword to a quad word.

That got me thinking, why/when do we sign extend for multiplication or division? In addition, when do we use instructions like cdq?

解决方案

As you can see from the insn ref manual (link in the tag wiki):

  • one-operand mul / imul: edx:eax = eax * src
  • two-operand imul: dst *= src

  • div / idiv: divides edx:eax by the src. quotient in eax, remainder in edx. There's no form of div / idiv that ignores edx in the input.
  • cdq sign-extends eax into edx:eax, i.e. broadcasts the sign bit of eax into every bit of edx. Not to be confused with cdqe, the 64bit instruction that does movsx rax, eax with fewer insn bytes.

    Originally (8086), there was just cbw (ax = sign_extend(al)) and cwd (dx:ax = sign_extend(ax)). The extensions of x86 to 32bit and 64bit have made the mnemonics slightly ambiguous (but remember, other than cbw, the within-eax versions always end with an e for Extend). There is no dl=sign_bit(al) instruction because 8bit mul and div are special, and use ax instead of dl:al.


Since the inputs to [i]mul are single registers, you never need to do anything with edx before a multiply.

If your input is signed, you sign-extend it to fill the register you're using as an input to the multiply e.g. with movsx or cwde (eax = sign_extend(ax)). If your input is unsigned, you zero extend. (With the exception that if you only need the low 16 bits of the multiply result, for example, it doesn't matter if the upper 16 bits of either or both inputs contain garbage.)


For a divide, you always need to zero or sign extend eax into edx. Zero-extending is the same as just unconditionally zeroing edx, so there's no special instruction for it. Just xor edx,edx.

cdq exists because it's a lot shorter than mov edx, eax / sar edx, 31 to broadcast the sign bit of eax to every bit in edx. Also, shifts with count > 1 didn't exist until 286, so on 8086, you'd need a loop if cwd didn't exist (the 16bit version of cdq).


In 64bit mode, sign and zero extending 32bit values to 64bit is common. The ABI allows garbage in the high 32bits of a 64bit register holding a 32bit value, so if your function is only supposed to look at the low 32bits of edi, you can't just use [array + rdi] to index the array.

So you see a lot of movsx rdi, edi (sign extend), or mov eax, edi (zero-extend, and yes it's more efficient to use a different target register, because Intel mov-elimination doesn't work with mov same,same)

这篇关于何时以及为什么我们签署扩展和使用干熄焦与MUL / DIV?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆