Intel平台Two's Complement Division算法符号扩展机制原理问询
Intel x86 整数除法规则的底层逻辑
为什么需要符号扩展
首先明确一个基础概念:符号扩展是有符号补码整数的等值位宽扩展操作。8位的-65补码是10111111,符号扩展为16位后是11111111 10111111,二者的整数值完全一致,只是位宽从8位变成了16位;同理正数的符号扩展和无符号数的零扩展也是等值转换,只是把高位补0。
x86的整数除法硬件默认要求输入的被除数位宽是除数的2倍:8位除法则输入16位被除数、16位除法则输入32位被除数,以此类推。这个设计是为了适配除法的硬件实现逻辑,避免运算过程中的移位溢出。
扩展得到的高位会被如何处理
x86的除法硬件采用的是逐位试商法,核心运算逻辑如下:
- 初始状态下,2倍位宽的被除数会被拆分为两部分:高位存入d寄存器(8位除法对应
%ah、32位对应%edx),作为初始余数值;低位存入a寄存器(8位对应%al、32位对应%eax),存储待运算的被除数位。 - 每一步运算会把d、a寄存器组成的整体左移1位,相当于把被除数的1位移到余数空间,然后用d寄存器的余数值减去除数:
- 如果够减,就把a寄存器的最低位设为1(商的对应位为1),保留减后的结果作为新的余数
- 如果不够减,就把a寄存器的最低位设为0(商的对应位为0),恢复余数为减之前的值
你举的65/3的例子里,初始高位全0就是初始余数,整个运算过程就是不断把低8位的被除数位移到高位余数空间做减法,和你手写的竖式逻辑完全一致。
对于负补码被除数的场景,符号扩展得到的全1高位就是余数的初始值,后续的试商逻辑会自动适配补码的运算规则,最终得到符合数学定义的结果:被除数 = 除数 * 商 + 余数,且余数符号和被除数一致。比如-65/3的结果就是商-21、余数-2,满足3*(-21) + (-2) = -65。
余数为什么最终存在d寄存器
从上面的运算逻辑就能看出来:整个运算过程中,d寄存器一直存的是当前的余数值,a寄存器存的是逐步生成的商。运算全部完成后,d寄存器自然就是最终的余数,a寄存器就是最终的商,这是硬件运算逻辑的自然结果,不是人为规定的存储位置。
内容的提问来源于stack exchange,提问作者Amittai Aviram
相关产品推荐
相关产品推荐

