我不太确定分区在x86汇编中是如何工作的(GAS AT&T语法).我想做的是划分两个长,然后将商乘以除数,看看新数是否等于初始数(n/m*m = n).
movl %ebx, %eax
movl %ecx, %edx
idivl %edx
imull %ebx, %edx
cmp %edx, %ebx
je .equal
Run Code Online (Sandbox Code Playgroud)
上面的代码是我做分工的片段.ebx和ecx是我想要分割的两个计数器,eax寄存器用作除数是否正确?所以,当我写idivl%edx时,我将edx与eax分开,并得到最接近0的整数?像7/2 = 3?我读了一个地方,这个商存储在edx寄存器中,余数存储在ah寄存器中,但我还被告知,商存储在eax寄存器中,余数存储在edx寄存器中,这让我感到困惑.
虽然这里的主要问题是:我想将ebx寄存器的值除以ecx寄存器的值,我该如何处理?
谢谢!
编辑:上面的代码产生一个浮点异常
该idiv指令在3个寄存器中有2个参数.
第一个隐式参数是被除数,edx:eax
低位32位的64位参数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
Run Code Online (Sandbox Code Playgroud)
你应该记住,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
我对ATT又称PDP语法有着强烈的仇恨,这种语法是荒谬而破碎的.
您可以使用.intel_syntax noprefix伪指令恢复健全并在Gas中使用Intel语法.
请参阅:我可以在GCC上使用x86汇编的Intel语法吗?