x86装配GAS部门
我还不太确定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
的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分区错误。
你得到一个整数除法错误的原因是你错误地使用了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汇编语言?
上一篇: Division in x86 Assembly GAS
下一篇: I am trying to program finite state machine in assembly language but i am stuck