Hi all,
I'm writing a routine to multiply signed 64 bit integers with catching overflow. Here's my code
.code
mult proc
; rcx == __int64 a
; rdx == __int64 b
; r8 == __int64 *lret
; r9 == double *dret
xorpd xmm0,xmm0
xorpd xmm1,xmm1
xor rax,rax
cvtsi2sd xmm0,rcx
cvtsi2sd xmm1,rdx
mulsd xmm0,xmm1
neg_chk:
xorpd xmm1,xmm1
xor r10,r10
cvtsi2sd xmm1,r10
comisd xmm0,xmm1
jb neg_int
jae pos_int
pos_int:
xorpd xmm1,xmm1
mov r10,9223372036854775807
cvtsi2sd xmm1,r10
comisd xmm0,xmm1
jbe dbl_as_int
ja as_dbl
neg_int:
xorpd xmm1,xmm1
mov r10,-9223372036854775808
cvtsi2sd xmm1,r10
comisd xmm0,xmm1
jae dbl_as_int
jb as_dbl
as_dbl:
movsd qword ptr[r9],xmm0
mov rax,1
jmp done
dbl_as_int:
cvttsd2si r10,xmm0
mov qword ptr[r8],r10
xor rax,rax
jmp done
done:
ret
mult endp
end
The corresponding signature I use in C
__int8 mult(__int64 a, __int64 b, __int64 *lval, double *dval);
This code works fine until it meets values a=2147452546 b=2147514748, in that case it delivers 4611686013165148160 instead of 4611686013165148408 . I'm just wondering what could possibly be going wrong? This seems to be an issue with the 128 bit arithmetics or conversion to 64 bit. Say, writing
push rdx
imul rdx,rcx
delivers correct. So wondering, how such an error can remotely happen with values of even bigger bitness? And, maybe there's a way to check this kind of thing through flags?
Thanks.