Hi guys.
I don`t know how to calculate two 64 bit long numbers,
"3A2C098FDE6273ED" with "26D371B41CA8B4F6" and that result "60FF7B43FB0B28E3" to show in MessageBox?
I`m using MASM for x86, btw.
Do i have to use the FPU registers and how? I would appreciate really a lot some code example!
Sorry for any mistakes. English is not my native language.
I only know how to calculate 32 bit long number with the FPU.
MyF_ proc
LOCAL P1_:QWORD
LOCAL P2_:QWORD
LOCAL Result_:QWORD
mov dword ptr [_P1],576ED371h
mov dword ptr [_P2],1AC54331h
FLD _FP1
FLD _FP2
FADD ST(0), ST(1)
fstp _Result
mov eax,dword ptr[_Result] ; eax = 723416A2
MyF_ endp
:t
You don't necessarily need to use the fpu for such an operation unless you have some other needs. Simply imagine you have to add 58+25 with paper and pencil.
5 8
+2 5
____
8 3
You would first add the lower part, keep the lower result, and carry over (when needed) the one for the addition of the higher part.
You use 32-bit registers for the lower and higher parts of 64-bit numbers.
.data
num1 qword 3A2C098FDE6273EDh
num2 qword 26D371B41CA8B4F6h
result qword ?
.code
mov eax,dword ptr num1 ;lower 32-bit part of num1
mov edx,dword ptr num1[4] ;higher 32-bit part of num1
add eax,dword ptr num2 ;add lower 32-bit part of num2 with lower 32-bit part of num1
adc edx,dword ptr num2[4] ;add with carry the higher 32-bit part of num2 with higher 32-bit part of num1
mov dword ptr result,eax ;mov the lower 32-bit part of the sum to the lower 32-bit part of result
mov dword ptr result[4],edx ;mov the higher 32-bit part of the sum to the higher 32-bit part of result
You can either use the result for further computations or convert it to ascii for display; you can use whatever algo you want for conversion but, if needed, you would find functions in the fpulib (umqtoa or smqtoa) to convert qwords to a decimal integers.
Omg, I'm embarrassed now.
Thank you so much for your answer, code example and fast reply!
It`s perfect and simple for asm. :t
Hi maelirou, welcome to the forum :icon14:
Quote from: raymond on March 31, 2016, 10:11:06 AM
You don't necessarily need to use the fpu for such an operation
Raymond is our FPU guru - don't take his advice too seriously:
fild num1
fild num2
fadd
fistp result
Much simpler, right?
Quoteyou can use whatever algo you want for conversion
If you are coming from a C/C++ background, you might be tempted to use
fprintf(). Here is an example:
include \masm32\include\masm32rt.inc
.data
num1 qword 3A2C098FDE6273EDh
num2 qword 26D371B41CA8B4F6h
result qword ?
.code
start:
fild num1
fild num2
fadd
fistp result
printf("The calculated sum is \t%I64X\n", result)
printf("The expected sum is\t%s\n", "60ff7b43fb0b28e3")
inkey "--- that was uncool, right? ---"
exit
end start
Output:
The calculated sum is 60FF7B43FB0B2800
The expected sum is 60ff7b43fb0b28e3
--- that was uncool, right? ---
Hex$() (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1198) does it properly but requires an extra library:
include \masm32\MasmBasic\MasmBasic.inc ; download (http://masm32.com/board/index.php?topic=94.0)
.data
num1 qword 3A2C098FDE6273EDh
num2 qword 26D371B41CA8B4F6h
result qword ?
Init
fild num1
fild num2
fadd
fistp result
PrintLine "The calculated sum is", Tb$, Hex$(result)
printf("The expected sum is\t%s\n", "60FF7B43 FB0B28E3")
inkey "--- that was cool, right? ---"
EndOfCodeOutput:
The calculated sum is 60FF7B43 FB0B28E3
The expected sum is 60FF7B43 FB0B28E3
But there is a shorter method to convince printf() to display
result correctly:
finit as first instruction after the start label ;-)
I verified the correct result with the Windows calculator, and included an integer calculation.
include \masm32\include\masm32rt.inc
.data
num1 qword 3A2C098FDE6273EDh
num2 qword 26D371B41CA8B4F6h
result qword ?
.code
start:
fild num1
fild num2
fadd
fistp result
printf("The calculated sum is \t%I64X\n\n", result)
; Init FPU for full 64-bit precision, instead of the
; 56-bit precision that Windows sets up.
finit
fild num1
fild num2
fadd
fistp result
printf("The calculated sum is \t%I64X\n\n", result)
mov eax, DWORD PTR num1[0]
mov ebx, DWORD PTR num2[0]
mov ecx, DWORD PTR num1[4]
mov edx, DWORD PTR num2[4]
; Add low-order DWORDs.
add eax, ebx
; Add high-order DWORDs with any carry from low-order addition.
adc ecx, edx
; Store results.
mov DWORD PTR result[0], eax
mov DWORD PTR result[4], ecx
printf("The calculated sum is \t%I64X\n\n", result)
printf("The expected sum is\t%s\n\n", "60ff7b43fb0b28e3")
inkey
exit
end start
The calculated sum is 60FF7B43FB0B2800
The calculated sum is 60FF7B43FB0B28E3
The calculated sum is 60FF7B43FB0B28E3
The expected sum is 60ff7b43fb0b28e3
Quote from: MichaelW on April 03, 2016, 04:28:04 PM
; Init FPU for full 64-bit precision, instead of the
; 56-bit precision that Windows sets up.
finit
That was indeed the point. Interesting that Raymond's example prints fine when using
printf("The result is %llx", result)
It seems printf() doesn't use the FPU at all, precision is still 53 bits when returning.
lea esi,x
lea ebx,y
lea edi,result
mov ecx,8
clc
@@: lodsb
adc al,[ebx]
stosb
inc ebx
loop @b
adc byte ptr [edi],0
Quote from: Mikl__ on April 25, 2016, 07:11:47 PM
lea esi,x
lea ebx,y
lea edi,result
mov ecx,8
clc
@@: lodsb
adc al,[ebx]
stosb
inc ebx
loop @b
adc byte ptr [edi],0
Inconvenient and buggy solution (Byte result[8] is modified).
See Raymond's post for compare:
Quote from: raymond on March 31, 2016, 10:11:06 AM
mov eax,dword ptr num1 ;lower 32-bit part of num1
mov edx,dword ptr num1[4] ;higher 32-bit part of num1
add eax,dword ptr num2 ;add lower 32-bit part of num2 with lower 32-bit part of num1
adc edx,dword ptr num2[4] ;add with carry the higher 32-bit part of num2 with higher 32-bit part of num1
mov dword ptr result,eax ;mov the lower 32-bit part of the sum to the lower 32-bit part of result
mov dword ptr result[4],edx ;mov the higher 32-bit part of the sum to the higher 32-bit part of result
Quote from: qWordInconvenient and buggy solution (Byte result[8] is modified)
Really? And it seemed to me is suitable both for 8-and for 64-bit microprocessors and doesn't depend on length of composed.
And if you add some 64-bit values (for example 0FFFFFFFFFFFFFFFFh and 1) the result can be 65-bit
QuoteReally?
You are correct that the addition of two 64-bit numbers could overflow and such a possibility must be incorporated in the code.
I think qWord's comment pertained to the fact that your "result" label was not defined in the code you provided. In many of the previous posts, it was defined as a qword (which does not have a 65th bit). Moreover, depending where your '8 bytes' would be reserved for storing the 64-bit result (such as on the stack), the next byte may not have been a '0' and adding 0 with carry to that next byte could be
buggy to use qWord's description.
Quoteinclude \masm32\include\masm32rt.inc
.686
.XMM
.data
q1 dq 03A2C098FDE6273EDh
q2 dq 026D371B41CA8B4F6h
qr dq 0
.code
start:
movq mm0, q1
movq mm1, q2
paddq mm0, mm1
movq qr, mm0
printf(" %I64Xh\n",q1)
printf("+ %I64Xh\n",q2)
printf("= %I64Xh\n\n",qr)
inkey
exit
end start
Quote3A2C098FDE6273EDh
+ 26D371B41CA8B4F6h
= 60FF7B43FB0B28E3h
Press any key to continue ...
Hi,
raymond!
Quote from: raymondI think qWord's comment pertained to the fact that your "result" label was not defined in the code you provided
I thought that it is obvious without explanations
.data
x dq 0F897654FDE6273EDh
y dq 26D371B41CA8B4F6h
result db 9 dup (0)
Quote from: Mikl__ on April 26, 2016, 05:18:03 PMresult db 9 dup (0)
When the result needs 9 bytes, the debate becomes a bit "academic". In practice, you should be aware of your limits, and if your program really needs 9 bytes, you'd better go for a REAL8. Or you go for Dave's Ling Long Kai Fang (http://masm32.com/board/index.php?topic=222.msg19324#msg19324) ;)
QuoteWhen the result needs 9 bytes, the debate becomes a bit "academic". In practice, you should be aware of your limits, and if your program really needs 9 bytes, you'd better go for a REAL8
Hi,
jj2007!
I don't understand what about we argue. If you add two N-byte unsigned integer numbers, then you reserve N+1-bytes for result. If you multiply two N-byte unsigned integer numbers, then you reserve 2*N bytes for result. Isn't it?
Sure, your logic is correct. But in real life, how would you handle (e.g. print) a "Q+1-WORD" variable, and why would you use one? A REAL8 has no such problems, and is only 0.0000000000000000001% less precise than the QWORD. That is why I consider the problem "academic". We argue about it because we like arguing...
QuoteWe argue about it because we like arguing...
Benissimo! (http://www.cyberforum.ru/images/smilies/popcorn.gif)
I love that icon :t Beer & chips for the lurkers, yeah :greensml:
Mikl__,
your solution is inconvenient because it needs 4 times more memory accesses than the classical approach, beside that the later one is branch-free. Also the results 8th Byte must be zeroed out before going into your code (static initialization does not count in general context).
Quote from: Mikl__ on April 26, 2016, 11:36:36 AMAnd it seemed to me is suitable both for 8-and for 64-bit microprocessors and doesn't depend on length of composed.
If you are interested in portability than you are wrong in using assembler. Your code might (depending on the memory addresses) run in x64, but I don't know any 8 Bit MCU that accept above code. Of course, the algorithm will work with any ISA that allows to add with carry.
QuoteI thought that it is obvious without explanations
In my opinion, this does not hold in assembly. I strongly believe in my signature "Whenever you assume ..."
Hi,
qWord!
Quoteyour solution is inconvenient because it needs 4 times more memory accesses than the classical approach, beside that the later one is branch-free. Also the results 8th Byte must be zeroed out before going into your code (static initialization does not count in general context).
maelirou didn't set a task of optimization of the program for speed or the volume occupied in memory. Your answers (at everything to you respect) are maintenance of dispute for the sake of the dispute
QuoteWe argue about it because we like arguing...
I will argue with c
;asm call
invoke calcul,OneReal,TwoReal,addr result
// Adding two REAL
int calcul(double truc,double chose,double * presult)
{
*presult = truc + chose;
return 0;
};
;32 bits
_calcul PROC ; COMDAT
; File h:\pratique\math_asm_c\feuille_calcul_c.c
; Line 21
push ebp
mov ebp, esp
sub esp, 64 ; 00000040H
push ebx
push esi
push edi
; Line 22
movsd xmm0, QWORD PTR _truc$[ebp]
addsd xmm0, QWORD PTR _chose$[ebp]
mov eax, DWORD PTR _presult$[ebp]
movsd QWORD PTR [eax], xmm0
; Line 23
xor eax, eax
; Line 24
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 0
_calcul ENDP
;64 bits
calcul PROC ; COMDAT
mov QWORD PTR [rsp+24], r8
movsd QWORD PTR [rsp+16], xmm1
movsd QWORD PTR [rsp+8], xmm0
push rbp
sub rsp, 64 ; 00000040H
mov rbp, rsp
movsd xmm0, QWORD PTR truc$[rbp]
addsd xmm0, QWORD PTR chose$[rbp]
mov rax, QWORD PTR presult$[rbp]
movsd QWORD PTR [rax], xmm0
xor eax, eax
lea rsp, QWORD PTR [rbp+64]
pop rbp
ret 0
calcul ENDP
QuoteI will argue with c
To continue the argument, which part of your code checks for overflow of 64-bit integers???
The cool thing with C is that there is just to ask and it is found
http://stackoverflow.com/questions/199333/how-to-detect-integer-overflow-in-c-c
http://stackoverflow.com/questions/15655070/how-to-detect-double-precision-floating-point-overflow-and-underflow
Quotewhich part of your code checks for overflow of 64-bit integers
I was asking about the code you actually posted as examples, and to be more specific when you used
floats to perform the addition.
none
but you have this solution for double
http://forums.codeguru.com/showthread.php?525081-double-overflow-detection