Help:Divide overflow error
From: ppw (ppw_at_pobox.net)
Date: 02/13/04
- Next message: Nathan C. Baker: "Pocket PC and ASM?"
- Previous message: Nathan C. Baker: "ASM for Pocket PC?"
- Next in thread: Phil Carmody: "Re: Help:Divide overflow error"
- Reply: Phil Carmody: "Re: Help:Divide overflow error"
- Reply: Tim Roberts: "Re: Help:Divide overflow error"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Fri, 13 Feb 2004 19:00:48 +0000 (UTC)
Hello. I would like to ask people if they could
help me with one algorithm, which seems OK to me,
but after the first IDIV instruction my program
from which the procedure (the algorithm) was called crashes to operating
system with 'Divide overflow' error message. If you could help me, I would
be really grateful. Thank you.
The point is:
My procedure ('powermod') performs this mathematic operation:
Y = X^S mod R
(X < R) for known X, S and R which are words (16bit).
>>From this is clear that we need to work with 32bit registers (e??).
Common arithmetic solution would be VERY slow and thus I know a better
way to solve this problem. The algorithm that does this is:
1) first, we will define S as a binary number:
S = s_0 + 2*s_1 + 4*s_2 + ... + 2^{k-1}*s_{k-1}
(we can say that S has k bits, in our case k = 16)
2) if s_0 = 1, then A := X, else A = 1
3) let Y_1 := X^2 mod R
(respectively Y_1 := Y_0^2 mod R, where Y_0 := X)
4) if s_1 = 1, then A := A*Y_1 mod R, else do not modify A
5) let Y_2 := Y_1^2 mod R
6) if s_2 = 1, then A := A*Y_2 mod R, else do not modify A
...
7) repeat steps 5) and 6) for Y_3 and s_3, Y_4 and s_4, ... , until
we reach Y_{k-1} and s_{k-1}
8) after k steps, A holds the result
My algorithm is below. PLEASE
suggest another solution. I would
REALLY appreciate it. Anyway, thanks for reading till now ;)
One more comment:
SI register holds offset to a bit mask (to get s_0, s_1, ... , s_15
values), where the bit masks are defined in data segment this way:
BitMasks dw 1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768
(1 = 0000000000000001b,
2 = 0000000000000010b,
4 = 0000000000000100b,
...
32768 = 1000000000000000b)
Thank you.
"XM"
OK, here's the code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; calculates equation: Y = X^S mod R (X < R)
; bx = X value
; cx = S value
; dx = R value
; regs destroyed: eax, ebx, cx, edx, si, edi
; return values: ax = Y value
powermod proc near
; set up ebx from bx
; mov di, bx ; this is the slow way
; xor ebx, ebx
; movzx ebx, di
movzx ebx, bx ; fast way
; set up edx from dx
; mov di, dx ; this is the slow way
; xor edx, edx
; movzx edx, di
movzx edx, dx ; fast way
; bit mask offset, initial is zero
xor si, si
; A value setup
; get s_0 value
mov di, cx
and di, BitMasks+2[si]
; autoincrement bit mask index
add si, 2
; is s_0 = 1?
or di, di
; if yes, go to nozero0
jnz notzero0
; s_0 = 0, so A = 1
; we will use EAX to hold A value
mov eax, 1
jmp begineqninit
notzero0:
; s_0 = 1, so A = X
mov eax, ebx
begineqninit:
; Y_0 setup
; we will use EDI to store Y_? values
; at the beginning EDI == Y_0 := X
mov edi, ebx
; follows the calculation loop
begineqn:
; Y_0^2 mod R ( = Y_1 ) follows
; (EDI^2 mod R respectively)
push eax
push ebx
mov eax, edi
mov ebx, edi
imul ebx
; save EDI^2 into EDI
; we will assume EDI is < 2^16 so EDI^2 will also fit into 32bit register
; comment: this is true since X is a word (16bit number)
; (so EDX -- upper 32 bits -- will be zeroes)
mov edi, eax
pop ebx
pop eax
; now EDI = Y_0^2, follows EDI mod R
push eax
push ebx
push edx
; EBX holds the divider (R)
mov ebx, edx
; EDX:EAX is the dividend (upper and lower 32bits)
; EDX is null, EAX = EDI
xor edx, edx
mov eax, edi
; comment:
; *** AT THIS POINT 'Divide overflow' IS GENERATED
; *** DON'T KNOW WHY...
idiv ebx
; EDX holds remainder - EDI mod R
; we will save this into EDI, now EDI := Y_0^2 mod R
mov edi, edx
pop edx
pop ebx
pop eax
; now EDI := Y_0^2 mod R == Y_1
push edi
; check for s_1 (s_2, ... , s_15)
mov di, cx
and di, BitMasks+2[si]
add si, 2
or di, di
jnz notzero1
pop edi
jmp powercont
notzero1:
; follows A := A*Y_1 mod R
; EAX = A, EDI = Y_1
pop edi
; A := A*Y_1
imul edi
; now EAX = A*Y_1, follows EAX mod R
push ebx
push edx
mov ebx, edx ; EBX is the divider (R)
xor edx, edx ; EDX is zero (upper 32bits of dividend)
; EAX is set (A)
idiv ebx
; EDX holds remainder - EAX mod R
; we will save this value into EAX (A)
mov eax, edx
pop edx
pop ebx
; now EAX == A := A*Y_1 mod R
powercont:
; are we at the end?
; when SI = 32 then we are, since after 16 steps SI = 16*2 = 32
cmp si, 32
jnz begineqn
; and now EAX (respectively AX) holds the result (X^S mod R)
ret
powermod endp
- Next message: Nathan C. Baker: "Pocket PC and ASM?"
- Previous message: Nathan C. Baker: "ASM for Pocket PC?"
- Next in thread: Phil Carmody: "Re: Help:Divide overflow error"
- Reply: Phil Carmody: "Re: Help:Divide overflow error"
- Reply: Tim Roberts: "Re: Help:Divide overflow error"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|
|