x86装配GAS部门

mmo*_*moe 2 x86 assembly 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
Run Code Online (Sandbox Code Playgroud)

上面的代码是我做分工的片段.ebx和ecx是我想要分割的两个计数器,eax寄存器用作除数是否正确?所以,当我写idivl%edx时,我将edx与eax分开,并得到最接近0的整数?像7/2 = 3?我读了一个地方,这个商存储在edx寄存器中,余数存储在ah寄存器中,但我还被告知,商存储在eax寄存器中,余数存储在edx寄存器中,这让我感到困惑.

虽然这里的主要问题是:我想将ebx寄存器的值除以ecx寄存器的值,我该如何处理?

谢谢!

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

Joh*_*ica 7

idiv指令在3个寄存器中有2个参数.
第一个隐式参数是被除数,edx:eax
低位32位的64位参数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
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.htmlhttp://www.felixcloutier.com/x86/DIV.html

对ATT又称PDP语法有着强烈的仇恨,这种语法是荒谬而破碎的.
您可以使用.intel_syntax noprefix伪指令恢复健全并在Gas中使用Intel语法.
请参阅:我可以在GCC上使用x86汇编的Intel语法吗?