我还不太清楚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寄存器的值,我该怎么办?
谢谢!
编辑:上面的代码产生浮点异常
答案 0 :(得分:7)
idiv
指令在3个寄存器中有2个参数
第一个隐式参数是被除数,edx:eax
中的64位参数
低32位在eax
中,高32位在edx
中
第二个显式参数是除数,在单个寄存器中是32位参数
由于显而易见的原因,除数应不为edx
或eax
。
结果以eax = Quotient,edx = Remainder返回。
知道正确的设置应该是:
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 Division错误。
你得到整数除法错误的原因是你错误地使用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
I have a burning hate对于ATT又称PDP语法,这是荒谬而破碎的
您可以使用.intel_syntax noprefix
伪指令恢复健全并在Gas中使用Intel语法
请参阅:Can I use Intel syntax of x86 assembly with GCC?