英文:
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 rax
and 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]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论