我还不太确定除法在 x86 汇编中是如何工作的(GAS AT&T 语法)。我想做的是将两个长整型相除,然后将商与除数相乘,看看新数字是否等于初始数字(n/m * m = n)。
movl %ebx, %eax
movl %ecx, %edx
idivl %edx
imull %ebx, %edx
cmp %edx, %ebx
je .equal
上面的代码是我进行除法的代码片段。
ebx
和ecx
是我想要除法的两个计数器,eax寄存器用作除数是否正确?所以当我写 idivl %edx
时,我将 edx
除以 eax
,然后得到最接近 0 的整数?比如 7/2 = 3?我读到一处说商存储在 edx
寄存器中,余数存储在 ah
寄存器中,但我也被告知商存储在 eax
寄存器中,余数存储在 edx
寄存器中,这让我很困惑。
虽然这里的主要问题是:我想将
ebx
寄存器的值除以 ecx
寄存器的值,但我应该如何进行?
编辑:上面的代码产生浮点异常
idiv
指令在3个寄存器中接受2个参数。edx:eax
eax
中,高 32 位在 edx
中。edx
或eax
。知道这一点,正确的设置应该是:
Intel syntax pdp-11 syntax
--------------------------------------------------------
.intel_syntax noprefix
mov ebx, dividend
mov ecx, divisor
mov eax,ebx movl %ebx, %eax
cdq cdq //edx:eax = 32 bit dividend
idiv ecx idivl %ecx //divide edx:eax by ecx
imul eax, ecx imull %ecx, %eax //multiply result by dividend
cmp ebx, eax cmpl %eax, %ebx
je .equal je .equal
add eax,edx addl %edx, %eax //add remainder
cmp ebx,eax cmpl %eax,%ebx //should be equal now
je .equal2 je .equal2
您应该记住,
div/idiv
执行整数除法!它不做任何浮点运算。仅当结果太大而无法容纳 32 位或除以零时,它才会生成异常,在这种情况下,您会收到 #DE 除法错误。
您收到整数除法错误的原因是您错误地使用
edx
作为除数,并且因为您的被除数是32位,所以高32位(存储在edx
中)始终为零,因此您有一个除以零。edx:eax idiv ecx
不适合 32 位(即,如果 edx:eax
相对于 ecx
太大),您将得到同样的错误。
请参阅:http://www.felixcloutier.com/x86/IDIV.html 和 http://www.felixcloutier.com/x86/DIV.html
我对 ATT 又名 PDP 语法怀有强烈的仇恨,它是无意义且破碎的。
您可以通过使用
.intel_syntax noprefix
伪指令来恢复理智并在 Gas 中使用 Intel 语法。