汇编 IA-32:如何将 64 位有符号数除以奇数(存储在 2 个寄存器中)

Posted

技术标签:

【中文标题】汇编 IA-32:如何将 64 位有符号数除以奇数(存储在 2 个寄存器中)【英文标题】:Assembly IA-32: How to divide 64-bit signed number by odd number (stored in 2 registers) 【发布时间】:2019-03-25 05:24:30 【问题描述】:

IA-32 架构上,我如何将 有符号 数除以 3(例如)存储在 2 个寄存器中的值 edx:eax( 64 位 值)。我想将整个值(64 位)除以 3,而不仅仅是 32 位,并将其存储在 2 个寄存器中。

我假设这只能使用 shifts 操作来完成,因为imul 仅适用于乘以 32 位数字。但只找到了除以2^n 数字的解决方案。

我怎样才能做到这一点?

【问题讨论】:

您想除以运行时变量数还是除以某个(但任何)常数? @harold 任意常数,可以除以1,2,3,4,5,6... 我修正了我的答案来处理正除数和签名股息。 Divide a number by 3 without using *, /, +, -, % operators 【参考方案1】:

您可以通过连续除法将任何长度数除以 32 位数,将前一次除法的余数用作下一次除法的被除数的最高 32 位,类似于长手除法

请注意,我需要修复此代码以处理负除数,但它应该适用于正除数和有符号除数。

请注意,此代码向负无穷大取整:-10/3:商 = -4,余数 = +2。为了处理负除数,代码可以同时取除除数和除数,然后取反余数。

        mov     ecx,000000003h  ;ecx = signed dvsr (must be positive)
        mov     edi,0fedcba98h  ;edi:esi = signed dvnd
        mov     esi,076543210h
        ;; inputs

        mov     eax,edi         ;eax = upper 32 bits dvnd
        cdq                     ; sign-extend that into EDX:EAX

        idiv    ecx
        test    edx,edx         ;br if sign rmdr == sign dvsr
        jns     short div0
        dec     eax             ;dec quot
        add     edx,ecx         ;rem += dvsr

div0:   mov     edi,eax         ;edi = upper 32 bits quot
        mov     eax,esi         ;eax = lower 32 bits dvnd
        div     ecx           
        mov     esi,eax         ;esi = lower 32 bits quot
;                               ;edx = remainder

【讨论】:

但这似乎不起作用,想象你正在做 -20306/3... 做同样的事情,但为了简化,我用 16 位(代表 64 位值)来做:10110000 10101110 ---> -20306 10110000 / 00000011 ---> -26 = 11100110 和 10101110 / 00000011 --> -27 = 11100101 所以结果值将是 11100110 11100101 和 1110010110061111 它的结果是 6跨度> 只有第一个分区是idiv,其余的都必须是udiv。 @DiogoSoares - 我错过了签名部分。我更新了处理正除数和签名股息的答案。 @rcgldr 实际上非常有用,谢谢。代码运行良好,但我不明白为什么这行有意义:add edx, ecx 紧跟在dec eax 之后。你能再赐教我一次吗 @DiogoSoares - 使用我回答中的示例,考虑情况 -10 / 3。X86 idiv 指令将返回商 = -3,余数 = -1,因为它将商四舍五入到零。但是,在这种情况下需要向负无穷大取整,因此 -10/3 的商为 -4,余数为 +2,为了得到这个结果,-3 的商递减为 -4,余数为 - 1 加上 3 得到 +2 的余数。

以上是关于汇编 IA-32:如何将 64 位有符号数除以奇数(存储在 2 个寄存器中)的主要内容,如果未能解决你的问题,请参考以下文章

汇编语言无符号数与有符号数转换

克服 x86 idiv #DE 异常

无符号数和有符号数的转化

汇编中的有符号-无符号-溢出-进位

汇编第六日

汇编语言中的符号拓展怎么理解,都有哪些规则