x86装配GAS部门

时间:2016-09-23 10:52:36

标签: assembly x86 att

我还不太清楚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寄存器的值,我该怎么办?

谢谢!

编辑:上面的代码产生浮点异常

1 个答案:

答案 0 :(得分:7)

idiv指令在3个寄存器中有2个参数 第一个隐式参数是被除数,edx:eax中的64位参数 低32位在eax中,高32位在edx中 第二个显式参数是除数,在单个寄存器中是32位参数 由于显而易见的原因,除数应edxeax
结果以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.htmlhttp://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?