[ASM] Odwrotność modulo n

0

Witam.

Męczę się z tym już dość długo i za nic nie mogę sobie z tym poradzić.

Otóż, implementacja funkcji modulo n w C++ :

int odwr_mod(int a, int n)
{
  int a0,n0,p0,p1,q,r,t;

  p0 = 0; p1 = 1; a0 = a; n0 = n;
  q  = n0 / a0;
  r  = n0 % a0;
  while(r > 0)
  {
    t = p0 - q * p1;
    if(t >= 0)
      t = t % n;
    else
      t = n - ((-t) % n);
    p0 = p1; p1 = t;
    n0 = a0; a0 = r;
    q  = n0 / a0;
    r  = n0 % a0;
  }
  return p1;
}

Natomiast ten kod napisałem w ASM :

;------------------------------------------------------------------------------	
	; zmienne pomocnicze
	LOCAL a0:DWORD, n0:DWORD, p0:DWORD, p1:DWORD, q:DWORD, r:DWORD, t:DWORD
	LOCAL temp:DWORD
;------------------------------------------------------------------------------

;------------------------------------------------------------------------------	
	; p0 = 0 
	mov eax, 0
	mov p0, eax
	
	; p1 = 1
	mov eax, 1
	mov p1, eax
	
	; a0 = a;
	mov eax, a
	mov a0, eax
	
	; n0 = n;
	mov eax, n
	mov n0, eax
;------------------------------------------------------------------------------



;------------------------------------------------------------------------------
	                              ; q  = n0 / a0;
	mov edx, 0
	mov eax, n0
	mov ecx, a0
	div ecx
	mov q, eax
;------------------------------------------------------------------------------




;------------------------------------------------------------------------------
                                  ;r  = n0 % a0;

	mov edx, 0
	mov eax, n0
	mov ecx, a0
	div ecx
	mov r, edx	
;------------------------------------------------------------------------------

	
	.WHILE r>0
		
		;------------------------------------------------------------------------------
		;t = p0 - q * p1;
		mov eax, q
		mul p1				; mnozenie q * p1
		mov temp, eax
		
		mov eax, p0
		sub eax, temp		; odejmowanie p0 - q*p1
		mov t, eax
		;------------------------------------------------------------------------------
		
		;if(t >= 0)
      	.IF t >= 0
      		; t = t % n;
      		mov edx, 0
      		mov eax, t
      		mov ecx, n
      		div ecx
      		mov t, edx
      	.ELSEIF
      		; t = n - ((-t) % n);
      		; zamiana t na liczbe ujemna
      		mov eax, t
      		neg eax
      		mov t, eax
      		
      		; dzielenie modulo
      		mov edx, 0
      		mov eax, t
      		mov ecx, n
      		div ecx
      		neg edx
      		mov temp, edx
      		mov eax, n
      		sub eax, temp
      		mov t, eax
      	.ENDIF
      	
      	;p0 = p1
      	mov eax, p1
      	mov p0, eax
      	
      	;p1 = t
      	mov eax, t
      	mov p1, eax
      	
      	;n0 = a0
      	mov eax, a0
      	mov n0, eax
      	
      	;a0 = r;
      	mov eax, r
      	mov a0, eax
      	
      	;q  = n0 / a0
      	mov edx, 0
      	mov eax, n0
      	mov ecx, a0
      	div ecx
      	mov q, eax
      	
    	;r  = n0 % a0
    	mov edx, 0
    	mov eax, n0
    	mov ecx, a0
    	div ecx
    	mov r, edx
		
	.ENDW
	
	mov eax, p1
	ret

Problem w tym, że nie generuje poprawnych wyników. Sądzę, że popełniłem błąd w tym fragmencie :

.ELSEIF
      		; t = n - ((-t) % n);
      		; zamiana t na liczbe ujemna
      		mov eax, t
      		neg eax
      		mov t, eax

Prosiłbym kogoś, żeby zerknął na kod.

Z góry dziękuję za pomoc.

Pozdrawiam.

0

Ok, poradziłem sobie.

Sama implementacja algorytmu jest w porządku.

Natomiast typ zmiennych lokalnych jest niepoprawny, ponieważ w pętli while operujemy już na liczbach ze znakiem, tak więc dla zwykłego DWORD (liczba ujemna będzie miała wartość np. 23131231...) warunek IF będzie zawsze spełniony.

Trzeba użyć typu SDWORD.

Może kiedyś się to komuś przyda :)

Pozdrawiam.

1 użytkowników online, w tym zalogowanych: 0, gości: 1