在x86-64上如何将无符号128/64位数相除?

huangapple go评论61阅读模式
英文:

How do divide unsigned 128/64 Bit on x86-64?

问题

我需要在一个64位处理器上将一个无符号128位数除以寄存器rdi中的64位除数,其中低位在rax中,高位在rdx中。然而,DIV指令只支持64/64位的除法。

我的方法是将rax中的低位保存在另一个寄存器中,并将rdx寄存器中的位按位左移到rax中,以执行与rdi的长除法,并将计算步骤保存在另一个寄存器中,逐步构建解决方案。

但我认为应该有一种更高效的方法。是否有支持在多个寄存器之间进行此类计算的指令?

英文:

I need to divide an unsigned 128-Bit number on a 64-Bit Processor at the Register rdx:rax with a 64-Bit divisor in rdi. The lower Bits are in raxand the higher ones in rdx.
However the DIV-Instruction only supports 64/64 Bit divisions.

My approach was to save rax, the lower Bits of the number, in another Register and left-shift the Bits from the rdx-Register bitwise into rax to perform a long division with rdi. And save the computational steps in another Register to build up the solution Step-by-Step.

But I think there has to be a more efficient approach. Are there instruction which support this kind of calculations between several Registers?

答案1

得分: 2

将存储在RDX:RAX中的无符号128位数除以存储在RDI中的64位数需要两次级联除法。在x86-64上,需要两次除法来将RDX:RAX中的128位值除以64位值。第一次除法将高位被除数(扩展为0)除以,产生高商。第二次除法将低位被除数(扩展为第一次除法的余数)除以,产生低商。我们返回第二次除法的余数,它存储在RCX中。

; 输入(RDX:RAX, RDI),输出(RDX:RAX, RCX)
mov     rcx, rax       ; 暂时将LowDividend存储在RCX中
mov     rax, rdx       ; 首先除以HighDividend
xor     edx, edx       ; 设置除法的RDX:RAX / RDI
div     rdi            ; -> RAX是HighQuotient,余数被重复使用
xchg    rax, rcx       ; 暂时将HighQuotient移动到RCX,将LowDividend恢复到RAX
div     rdi            ; -> RAX是LowQuotient,余数是RDX
xchg    rdx, rcx       ; 在RDX:RAX中构建真正的128位商
ret                    ; 并将余数返回到RCX=[0, RDI-1]
英文:

Dividing the unsigned 128-bit number held in RDX:RAX by the 64-bit number held in RDI

On x86-64 a cascade of 2 divisions is needed to divide the 128-bit value in RDX:RAX by a 64-bit value.
The 1st division divides the high dividend (extended with 0) yielding a high quotient. The 2nd division divides the low dividend (extended with the remainder from the 1st division) yielding the low quotient. It's the remainder from the 2nd division that we return in RCX.

; IN (RDX:RAX,RDI) OUT (RDX:RAX,RCX)
    mov     rcx, rax       ; Temporarily store LowDividend in RCX
    mov     rax, rdx       ; First divide the HighDividend
    xor     edx, edx       ; Setup for division RDX:RAX / RDI
    div     rdi            ; -> RAX is HighQuotient, Remainder is re-used
    xchg    rax, rcx       ; Temporarily move HighQuotient to RCX restoring LowDividend to RAX
    div     rdi            ; -> RAX is LowQuotient, Remainder RDX
    xchg    rdx, rcx       ; Build true 128-bit quotient in RDX:RAX
    ret                    ; and return remainder in RCX=[0,RDI-1]

huangapple
  • 本文由 发表于 2023年4月20日 06:26:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76059245.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定