Assembly 用edi代替eax求最大公约数
我试图写一个代码来找到最大公约数(GCD)。我编写的代码工作得非常好,但是我需要使用EDI寄存器而不是EAX寄存器来编写相同的代码。但当我在代码中将“EAX”替换为“EDI”时,它并没有按预期工作。我相信问题出在DIV身上(尽管不确定)Assembly 用edi代替eax求最大公约数,assembly,x86,masm,greatest-common-divisor,Assembly,X86,Masm,Greatest Common Divisor,我试图写一个代码来找到最大公约数(GCD)。我编写的代码工作得非常好,但是我需要使用EDI寄存器而不是EAX寄存器来编写相同的代码。但当我在代码中将“EAX”替换为“EDI”时,它并没有按预期工作。我相信问题出在DIV身上(尽管不确定) div指令(以及idiv指令)使用隐含的(“硬连线”)寄存器来分配红利、商和余数;只有除数是显式的(由程序员决定) 更具体地说,股息必须在(e/r)dx:(e/r)ax中,商将放在(e/r)ax中,剩余部分将放在(e/r)dx中。在您的情况下(32位,以esi作
div
指令(以及idiv
指令)使用隐含的(“硬连线”)寄存器来分配红利、商和余数;只有除数是显式的(由程序员决定)
更具体地说,股息必须在(e/r)dx:(e/r)ax
中,商将放在(e/r)ax
中,剩余部分将放在(e/r)dx
中。在您的情况下(32位,以esi
作为除数),64位被除数必须在edx:eaz
中(或者,用edx
中的最高32位和eax
中的最低32位分成两半)
除了div
和idiv
指令之外,没有其他选择(除了它们本身-即,您可以使用idiv
而不是div
,但它不会有帮助),因为没有其他选择,您需要将值从edi
移动/复制到eax
(并将结果从eax
移动/复制回edi
);如果这样移动/复制值,最好在循环外部(而不是在循环内部)进行
换句话说,您希望您已经拥有的几乎所有代码(使用eax
)保持不变,并且只希望在开始时使用mov-eax,edi
,在结束时使用mov-edi,eax
(如果eax
,则可能使用push-eax
和pop-eax
)
另一个选项是期望调用者将值放入
eax
本身,这可能更有效(因为调用者可能对它用于什么的寄存器没有太多限制);但这可以转化为“停止想做你想做的事情”。指令(和idiv
指令)使用隐含(“硬连线”)寄存器进行除数、商和余数;只有除数是显式的(由程序员确定)
更具体地说,被除数必须是(e/r)dx:(e/r)ax
,商将被放入(e/r)ax
,其余部分将被放入(e/r)dx
。在您的情况下(32位,以esi
作为除数),64位被除数必须是edx:eaz
(或者,将edx中的最高32位和eax中的最低32位一分为二)
除了div
和idiv
指令之外,没有其他选择(除了它们本身-即,您可以使用idiv
而不是div
,但它不会有帮助),因为没有其他选择,您需要将值从edi
移动/复制到eax
(并将结果从eax
移动/复制回edi
);如果这样移动/复制值,最好在循环外部(而不是在循环内部)进行
换句话说,您希望您已经拥有的几乎所有代码(使用eax
)保持不变,并且只希望在开始时使用mov-eax,edi
,在结束时使用mov-edi,eax
(如果eax
,则可能使用push-eax
和pop-eax
)
另一个选项是期望调用者将值放入
eax
本身,这可能会更有效(因为调用者可能对它用于什么的寄存器限制更少);但这可以转化为“停止想做你想做的事情”.DIV
使用(e/r)ax
和(e/r)dx
的组合作为红利。请参阅英特尔手册。DIV
使用(e/r)ax
和(e/r)dx
的组合作为红利。请参阅英特尔手册。
.386
.model flat, Stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD
.data
x sword 33
y sword 242
.code
main proc
mov eax, 0
mov esi, 0
mov ax, x
mov si, y
main endp
;----------
CalcGCD Proc ;calculate greatest common divisor
;receive x in eax(int 1) and y in esi(int 2)
;returns x in eax = gcd
;----------
push esi
push edx
cmp eax,0 ;if x >=0
jge LX
neg eax ; x was negative, so make negative
LX:
cmp esi,0 ;if y >=0
jge LY
neg esi ; y was negative, so make negative
LY:
DO: mov edx,0
DIV esi ; edx= eax%esi
mov eax, esi ;eax =esi
mov esi,edx ;esi=edx
cmp esi, 0 ;while esi>0
jg do ;jump back to DO
pop edx
pop esi
ret
CalcGCD ENDP
end main