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.