Witam.

Problem pewnie banalny, ale chyba wykorzystałem już wszystkie opcje.

Otóż napisałem w asemblerze trzy procedury :

  1. FuncNwd PROC la:DWORD, lb:DWORD
    Oblicza największy wspólny dzielnik dwóch liczb

  2. FuncModulo PROC a:DWORD, n:DWORD
    Procedura obliczająca odwrotność modulo n

  3. FuncGenerateKey PROC
    Procedura generująca klucz publiczny i prywatny

Oto ich kod

FuncNwd PROC la:DWORD, lb:DWORD

	LOCAL NWDZmienna:DWORD
	LOCAL NWDReszta:DWORD
		
		mov edx, 0
		mov ecx, 0
		.WHILE lb!=0
			mov eax, lb
			mov NWDZmienna, eax		
			mov eax, la
			mov ecx, lb
			mov edx, 0
			div ecx
			mov NWDReszta, edx
			mov eax, NWDReszta
			mov lb, eax
			mov eax, NWDZmienna
			mov la, eax
			mov edx, 0
			mov ecx, 0
		.ENDW
		
	mov eax, la
	ret
FuncNwd ENDP
FuncModulo PROC a:DWORD, n:DWORD

	; zmienne
	LOCAL a0:DWORD, n0:DWORD, p0:DWORD, p1:DWORD, q :DWORD, r :DWORD, t :DWORD, temp:DWORD
	; zmienna pomomcnicze
	LOCAL test1:DWORD, test2:DWORD
	
	;inicjalizacja zmiennych
	mov eax, 0
	mov p0, eax  ;p0 = 0
	
	;inicjalizacja zmiennych
	mov eax, 1
	mov p1, eax  ;p1 = 1
	
	;inicjalizacja zmiennych
	mov eax, a
	mov a0, eax  ; a0 = la
	
	;inicjalizacja zmiennych
	mov eax, n
	mov n0, eax  ; n0 = n
	
	;zerowanie rejestrów eax, edx, ecx
	mov eax, 0
	mov edx, 0
	mov ecx, 0
	;inicjalizacja zmiennych
	
	; q = n0 / a0
	mov eax, n0
	mov ecx, a0
	mov edx, 0		;obliczenie wyniku dzielenia n0 przez a0
	div ecx
	mov q, eax		;wynik dzielenia w rejestrze eax
	
	; r = n0 % a0
	mov eax, n0
	mov ecx, a0
	mov edx, 0		;obliczanie dzielenia modulo
	div ecx
	mov r, edx		;reszta z dzielenia w rejestrzea edx
	
	
	.WHILE r > 0
		; t = p0 - q * p1
		mov eax, q
		mul p1
		mov temp, eax

		mov eax, p0
		sub eax, temp
		mov t, eax
		
		.IF t>=0
		    ; t = t % n
			mov eax, t
			mov ecx, n
			mov edx, 0
			div ecx
			mov t, edx ;reszta z dzielenia
		.ELSEIF
			; zamiana zmiennej t na znak przecziwny -t
			mov eax, t
			neg eax
			mov t, eax
			; dzielenie modulo
			mov eax, t
			mov ecx, n
			mov edx, 0
			div ecx
			neg edx
			mov temp, edx
			mov eax, n
			add eax, temp
			mov n, eax
		.ENDIF
		mov eax, p1
		mov p0, eax
		
		mov eax, t
		mov p1, eax
		
		mov eax, a0
		mov n0, eax
		
		mov eax, r
		mov a0, eax
		
		mov eax, n0
		mov ecx, a0
		mov edx, 0
		div ecx
		mov q, eax
		
		mov eax, n0
		mov ecx, a0
		mov edx, 0
		div ecx
		mov r, edx
	.ENDW

	; p1 wynik diałania funkcji

	mov eax, p1
	ret
FuncModulo ENDP

; generowanie klucza dla liczb 111 oraz 433

FuncGenerateKey PROC
	LOCAL p:DWORD, q:DWORD
	LOCAL phi:DWORD, n:DWORD, e:DWORD, d:DWORD
	LOCAL licznik:DWORD
	
	mov p, 111
	mov q, 433
	
	sub p, 1
	sub q, 1
	
	mov eax, p
	mul q
	mov phi, eax
	
	mov p, 111
	mov q, 433
	
	mov eax, p
	mul q
	mov n, eax
		
    
    mov e, 3
    invoke FuncNwd,e,phi    
    .WHILE eax != 1
		add e, 2
		invoke FuncModulo,e,phi
		mov d, eax
		invoke FuncNwd,e,phi
    .ENDW
	
	ret
FuncGenerateKey  ENDP

Problem w tym, iż klucz prywatny (zmienne e oraz n) generuje poprawnie, tak jak implementacja w C++.

Niestety nie generuje poprawnie klucza publicznego (zmienna d).

Implemetacja w C++ wygląda następująco :

Największy wspólny dzielnik

int nwd(int a, int b)
{
  int t;

  while(b != 0)
  {
    t = b;
    b = a % b;
    a = t;
  };
  return a;
}

Funkcja obliczająca odwrotność modulo n

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;
}

Generowanie kluczy :

    int p,q,phi,n,e,d;

    int eax;

    p = 111;
    q = 433;

      phi = (p - 1) * (q - 1);
      n   = p * q;

    // wyznaczamy wykładniki e i d

    e=3;
    eax = nwd(e,phi);
    while (eax != 1)
    {
            e = e+2;
            d = odwr_mod(e,phi);
            eax=nwd(e,phi);
    }

EDIT :

Jeśli procedury wywoływane są osobno (dla testów) to zwracają takie same wartości jak te napisane w C++

Pewnie coś źle zaimplementowałem w asemblerze. Najprawdopodobniej chodzi o pętlę w procedurze odpowiedzialnej za generowanie kluczy, ale nie jestem pewien.

Prosiłbym kogoś o zerknięcie na kod i o jakieś rady.

Z góry dziękuję za odpowiedź.

Pozdrawiam.