;******************************************************************************
;*                                                                            *
;*  Arithmetik und Zahlentheorie-Funktionen fuer grosse Zahlen in C           *
;*  Software zum Buch "Kryptographie in C und C++"                            *
;*  Autor: Michael Welschenbach                                               *
;*                                                                            *
;*  Quelldatei umul.asm    Stand: 27.05.2000                                  *
;*                                                                            *
;*  Copyright (C) 1998-2001 by Michael Welschenbach                           *
;*  Copyright (C) 1998-2001 by Springer-Verlag Berlin, Heidelberg             *
;*                                                                            *
;*  All Rights Reserved                                                       *
;*                                                                            *
;*  Die Software darf fuer nichtkommerzielle Zwecke frei verwendet und        *
;*  veraendert werden, solange die folgenden Bedingungen anerkannt werden:    *
;*                                                                            *
;*  (1) Alle Aenderungen muessen als solche kenntlich gemacht werden, so dass *
;*      nicht der Eindruck erweckt wird, es handle sich um die Original-      *
;*      Software.                                                             *
;*                                                                            *
;*  (2) Die Copyright-Hinweise und die uebrigen Angaben in diesem Feld        *
;*      duerfen weder entfernt noch veraendert werden.                        *
;*                                                                            *
;*  (3) Weder der Verlag noch der Autor uebernehmen irgendeine Haftung fuer   *
;*      eventuelle Schaeden, die aus der Verwendung oder aus der Nicht-       *
;*      verwendbarkeit der Software, gleich fuer welchen Zweck, entstehen     *
;*      sollten, selbst dann nicht, wenn diese Schaeden durch Fehler verur-   *
;*      sacht wurden, die in der Software enthalten sein sollten.             *
;*                                                                            *
;******************************************************************************
;******************************************************************************
;*                                                                            *
;*      Multiplikation, Schnittstelle wie bei C-Funktion umul_l()             *
;*                                                                            *
;*      Produkt:=a*u                                                          *
;*                                                                            *
;*      Stack bei Aufruf von umul:        SP+12 ---> Offset   Produkt         *
;*                                        SP+ 8 ---> Offset   a (CLINT)       *
;*                                        SP+ 4 ---> Offset   u (USHORT)      *
;*                                        SP    ---> Return Adresse           *
;*                                                                            *
;*      Return Value: ax = 0                                                  *
;*                                                                            *
;******************************************************************************
PUBLIC  umul

.386
.MODEL  FLAT
.CODE
umul    proc    near
;
a       equ     0000                    ; CLINT-Faktor  (Arbeitskopie)
p       equ     0520                    ; Produkt       (Arbeitsspeicher)
;
_a      equ     [ebp+8]                 ; CLINT-Faktor  (Parameter)
_u      equ     [ebp+12]                ; USHORT-Faktor (Parameter)
_p      equ     [ebp+16]                ; Produkt (Ergebnisspeicher)
;
WORKSP  equ     1560                    ; Arbeitsspeicher auf dem Stack
;
umult:  push    ebp                     ; Sichern fuer C-Funktion
        mov     ebp,esp
        sub     esp,WORKSP              ; Lokaler Speicher
        mov     eax,esp                 ;   Startadresse sichern
        push    edi
        push    esi
        push    ebx
        mov     ebx,eax
;
        xor     eax,eax
        xor     edx,edx

        mov     dx,_u                   ; USHORT-Faktor in dx
        cmp     dx,0
        jne     @F
        jmp     umultz

@@:     mov     esi,_a                  ; Segment:Offset von Var a
        mov     ax,[esi]
        cmp     ax,0                    ; a = 0 ?
        jne     umult01
        jmp     umultz
;
;>>>>>> Lade Operanden
;
umult01:
        lea     edi,a[ebx]              ; Zieloffset ist a[ebx]
        mov     ecx,0
        mov     cx,ax                   ; l(a) in ecx
        cld
rep     movsw                           ; Lade a wortweise in a
        movsw                           ;  plus ein Wort
        mov     word ptr [edi],0
;
;>>>>>> Adressierung des lokalen Arbeitsspeichers vorbereiten
;
        push    ebp                     ; BP retten
        mov     ebp,ebx                 ; Basisind. Adr. in SS
;
;>>>>>>> Reduziere Darstellung der Operanden um fuehrende Nullen
;
        xor     eax,eax
        mov     ax,a[ebp]               ; #USHORTs in ax
        cmp     ax,0
        je      end1
        shl     eax,1                   ; #Bytes
        mov     esi,eax
@@:     cmp     word ptr a[ebp][esi],0  ; USHORT = 0 ?
        jne     @F                      ; Nein, dann fertig
        sub     esi,2                   ; Sonst: ein USHORT zurck
        cmp     esi,0                   ; Index schon auf Minimum?
        je      mazer1                  ; Dann Zahl = 0
        jmp     @B                      ; Naechster Vergleich
@@:
mazer1: shr     esi,1                   ; #USHORTs
        mov     eax,esi                 ; ... in ax uebertragen
        mov     a[ebp],ax               ; ... und speichern
;
@@:
end1:   cmp     ax,0
        jne     @F
        pop     ebp
        jmp     umultz
;
;>>>>>> Beginn der Multiplikation
;
;-----> Arbeitsfeld initialisieren
;
@@:     mov     esi,2                   ; Initialisierung des Index i
        mov     cx,a[ebp]               ; l(a)
        shr     cx,1
        jnc     umult0
        inc     cx
umult0: mov     eax,0
umult1: mov     p[ebp][esi],eax
        add     esi,4
        loop    umult1
;
;-----> Innere Schleife
;
        mov     edi,2                   ; Index j
        mov     cx,a[ebp]               ; Zaehler innere Schleife initialisieren
        shr     cx,1
        jnc     umult2a
        inc     cx
umult2a:
        xor     ebx,ebx
        mov     bx,dx                   ; USHORT-Faktor in bx aufbewahren
        mov     edx,0                   ; Dummy-Uebertrag
        mov     esi,2
        mov     edi,2
umult3: push    ecx                     ; Zaehler retten
        mov     ecx,edx                 ; Uebertrag u in dx
        mov     eax,ebx                 ; USHORT-Faktor in ax laden
        mul     dword ptr a[ebp][edi]   ; ax=lo, dx=hi
        add     eax,ecx                 ; ax + u
        adc     edx,0
        add     p[ebp][esi],eax         ; p[i+j-1]= ax + p[i+j-1]
        adc     edx,0                   ; neuer Uebertrag u in dx
        add     edi,4                   ; j=j+4
        add     esi,4                   ; i+j=i+j+4
        pop     ecx                     ; Inneren Zaehler holen
        loop    umult3
;
;-----> Ende innere Schleife
;
        mov     p[ebp][esi],edx         ; p[i+j-1]=u
        add     esi,2
umult3a:
        cmp     word ptr p[ebp][esi],0
        jne     short umult4
        sub     esi,2
        jmp     umult3a
umult4: mov     ecx,esi
        shr     ecx,1
        mov     p[ebp],cx
;
;-----> Produkt speichern
;
        lea     esi,p[ebp]
        mov     ebx,ebp
        pop     ebp
        mov     edi,_p

        cmp     cx,0
        je      @F
        cld                             ; l(p) ist noch im Zaehlerregister cx
rep     movsw
@@:     movsw
;
;*******************************************************************************
;       Security: Stack lschen

muret:  mov     edi,ebx
        mov     ecx,(WORKSP-4)/4
        cld
        mov     eax,0                   ; Return-Value = 0: alles OK
rep     stosd                           ; Ueberschreibe mit 0
;*******************************************************************************
;
        pop     ebx
        pop     esi                     ; Wiederherstellen
        pop     edi
        mov     esp,ebp
        pop     ebp
        ret
;
umultz: mov     esi,_p
        mov     word ptr [esi],0
        jmp     short muret
;
umul    endp
END

