ProgrAmerica
ProgrAmerica

Reputation: 1

Finding greatest common divisor using edi instead of eax

I'm trying to write a code to find the greatest common divisor (GCD). The code I wrote works perfectly fine, but I need to write the same code using the EDI register instead of the EAX register. But when I replace "EAX" with "EDI" in the code, it doesn't work as intended. I believe the issue is with the DIV(not sure though)...

.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

Upvotes: 0

Views: 99

Answers (1)

Brendan
Brendan

Reputation: 37212

The div instruction (and the idiv instruction) uses implied ("hard wired") registers for the dividend, the quotient and the remainder; and only the divisor is explicit (determined by the programmer).

More specifically, the dividend must be in (e/r)dx:(e/r)ax, the quotient will be put in (e/r)ax and the remainder will be put in (e/r)dx. In your case (32-bit with esi as the divisor) the 64-bit dividend must be in edx:eaz (or, split in half with the highest 32 bits in edx and the lowest 32 bits in eax).

There's no alternative to the div and idiv instructions (except for themselves - i.e. you could use idiv instead of div but it won't help), and because there's no alternative you will need to move/copy values from edi into eax (and move/copy the result from eax back to edi); and if you're moving/copying values like that it's nicer to do it outside the loop (and not inside the loop).

In other words, you want almost all of the code that you already had (that uses eax) to remain the same, and just want a mov eax,edi at the start and a mov edi,eax at the end (possibly with push eax and pop eax if eax is supposed to be unmodified).

The other option is to expect the caller to put the value in eax themselves, and this is likely to be more efficient (because the caller is likely to have less restrictions on which registers it uses for what); but that can be translated into "stop wanting to do what you wanted to do".

Upvotes: 2

Related Questions