.MODEL SMALL,C .386 ;80386-Assemblierung ermöglichen public fpadd ;Assembler-Funktion veröffentlichen extrn fpadd_v:word ;Word zur Anzeige eines Overflow ; a und b sind long doubles, c ein Zeiger auf ein long double ; Offset Länge Bedeutung ; 0 8 Mantisse ; 8 2 Exponent mit Vorzeichen-Bit (Bit 15) .CODE fpadd PROC near ARG a:byte:10, b:byte:10, c:word USES ax, bx, cx, dx ;Stack-Offsets definieren manA equ 4 ;Offset von bp expA equ 12 ;Offset von bp manB equ 14 ;Offset von bp expB equ 22 ;Offset von bp manC equ 0 ;Offset von [c] expC equ 8 ;Offset von [c] ;______________________________________________________________________ ;Overflow-Flag löschen mov fpadd_v,0 ;(1) shift = exponentA - exponentB mov ax,[bp+expA] mov dx,[bp+expB] and ax,7fffh and dx,7fffh ;ax/dx enthalten expA/expB mov cx,ax sub cx,dx ;cx = shift ;______________________________________________________________________ ;(2) ist shift positiv oder negativ? mov bx,c ;bx => C js shiftA shiftB: ;shift ist positiv mov [bx+expC],ax ;exponentC = exponentA, signC="+" cmp cx,0 je shifted ;Sonderfall: Exponenten bereits gleich cmp cx,64 jae shiftB3 ;wenn shift >= 64, mantisseB = 0 mov eax,[bp+manB] mov edx,[bp+manB+4] cmp cx,32 jb shiftB1 mov eax,edx ;um 32 Bit schieben => eax=edx, edx=0 mov edx,0 sub cx,32 shiftB1: ;mantissaB um shift nach rechts schieben shrd eax,edx,cl shr edx,cl mov [bp+manB],eax mov [bp+manB+4],edx jmp shifted ;_______________ shiftA3: mov dword ptr [bp+manA],0 mov dword ptr [bp+manA+4],0 jmp shifted shiftB3: mov dword ptr [bp+manB],0 mov dword ptr [bp+manB+4],0 jmp shifted ;_______________ shiftA: ;shift ist negativ mov [bx+expC],dx ;exponentC = exponentA, signC="+" neg cx cmp cx,64 jae shiftA3 ;wenn shift >= 64, mantisseA = 0 mov eax,[bp+manA] mov edx,[bp+manA+4] cmp cx,32 jb shiftA1 mov eax,edx ;um 32 Bit schieben => eax=edx, edx=0 mov edx,0 sub cx,32 shiftA1: ;mantissaA um shift nach rechts schieben shrd eax,edx,cl shr edx,cl mov [bp+manA],eax mov [bp+manA+4],edx ; jmp shifted ;______________________________________________________________________ shifted: ;bx zeigt immer noch auf C ;Mantissen sind jetzt so verschoben, daß die Exponenten gleich sind mov cx,[bp+expA] bt cx,15 ;ist A negativ? jnc shifted1 or word ptr [bx+expC],08000h ;signC = signA shifted1: mov dx,[bp+expB] ;jetzt cx/dx = exponentA/B mov ax,cx xor ax,dx ;sind die Vorzeichen von A und B gleich? js signdiff ;_______________ ;(3) Vorzeichen gleich; mantissaC = mantissaA + mantissaB ; bx zeigt immer noch auf C signsame: mov eax,[bp+manA] mov edx,[bp+manB] add eax,edx ;niedrigere 32 Bit in eax mov ecx,[bp+manA+4] mov edx,[bp+manB+4] adc ecx,edx ;höhere 32 Bit in ecx jc signsame2 jne signsame3 ;Mantisse ist Null => Exponent auf +Null setzen mov word ptr [bx+expC],0 ;kein Übertrag => Ergebnis sofort speichern, fertig signsame3: mov [bx+manC],eax mov [bx+manC+4],ecx ret ;_______________ ;Übertrag; manC nach rechts schieben, expC erhöhen signsame2: rcr ecx,1 ;Carry gesetzt, daher wird 1 nachgeschoben rcr eax,1 inc word ptr [bx+expC] mov dx,[bx+expC] and dx,7FFFh cmp dx,7FFFh jne signsame3 ;kein Overflow => fertig ;(expC == 32767) => Overflow-Fehler mov dword ptr [bx+manC],0 ;c auf legalen Wert setzen mov dword ptr [bx+manC+4],0 mov word ptr [bx+expC],0 mov word ptr fpadd_v,0FFFFh ;Overflow-Variable auf true setzen ret ;______________________________________________________________________ ;(4) Vorzeichen verschieden; mantissaC = mantissaA - mantissaB ; bx zeigt immer noch auf C signdiff: mov eax,[bp+manA] mov edx,[bp+manB] sub eax,edx ;niedrigere 32 Bit in eax mov ecx,[bp+manA+4] mov edx,[bp+manB+4] sbb ecx,edx ;höhere 32 Bit in ecx jnc signdiff2 ;_______________ ;Übertrag => mantissaC = -mantissaC; signC = !signC neg eax jnc signdiff3 inc ecx signdiff3: neg ecx xor word ptr [bx+expC],8000h ;_______________ signdiff2: ;kein Übertrag mov edx,eax or edx,ecx ;mantissaC == 0 ? je signdiff4 ;ja bt ecx,31 ;muß verschoben werden? jc signdiff6 ;nein ;mantissaC so lange nach links verschieben, bis Bit 63 gesetzt ist mov dx,[bx+expC] stc ;Carry-Flag setzen! signdiff5: rcl eax,1 ;beim ersten Mal 1, sonst 0 nachschieben rcl ecx,1 dec dx ;exponentC um 1 verringern bt ecx,31 jnc signdiff5 mov [bx+expC],dx signdiff6: ;Ergebnis speichern mov [bx+manC],eax mov [bx+manC+4],ecx ret ;_______________ ;mantissaC ist Null => exponentC = +Null, fertig signdiff4: mov dword ptr [bx+manC],0 mov dword ptr [bx+manC+4],0 mov word ptr [bx+expC],0 ret fpadd ENDP END