Hello again everyone.
I study assembly language as hobby and now I'm working on my little 'File Explorer' project and I need several basic functions to manipulate QWORD values.
I looked for those functions in the masm32 library but found nothing.
So I coded all those functions but I'm sure it's not good enough, I need it fast.
Take a look at one of those functions I coded:
;add two QWORD values, return (0=success, 1=overflow)
qwadd PROC lpSrc1:DWORD, lpSrc2:DWORD, lpDest:DWORD
push edi
push esi
mov esi, lpSrc1
mov edi, lpSrc2
xor eax, eax
mov ecx, dword ptr [esi]
mov edx, dword ptr [esi+4]
add ecx, dword ptr [edi]
adc edx, 0
add edx, dword ptr [edi+4]
adc eax, 0
mov edi, lpDest
mov dword ptr [edi], ecx
mov dword ptr [edi+4], edx
pop esi
pop edi
ret
qwadd ENDP
Please help me find the fastest function to do basic stuffs with qword values (add, sub, mul, div, convert to/from ascii, etc.).
Thank you.
PS. In Thailand where I was born and living, Assembly language is not so popular.
Even in university they teach C, C++, C#, Java and everything but no Assembly.
No books, no websites or classrooms about 32 bits assembly language exist.
I'm sad. :(
You can perform qword arithmetic with the following macro's:
Addition and subtraction:
; eax:edx = eax:edx + srclow:srchigh
qwadd macro srclow:req, srchigh:req
add eax, srclow
adc eax, srchigh
endm
; eax:edx = eax:edx - srclow:srchigh
qwsub macro srclow:req, srchigh:req
sub eax, srclow
subb eax, srchigh
endm
Multiplication is a bit harder, but no big deal: (this functions results in a double quadword - 128 bits)
qwmul proc pdst:dword, alow:dword, ahigh:dword, blow:dword, bhigh:dword
push edi
mov edi, pdst
mov [edi + 8], 0
mov [edi + 12], 0
mov eax, alow
mul blow
mov [edi + 0], eax
mov [edi + 4], edx
mov eax, ahigh
mul blow
add [edi + 4], eax
adc [edi + 8], edx
mov eax, alow
mul bhigh
add [edi + 4], eax
adc [edi + 8], edx
mov eax, ahigh
mul bhigh
add [edi + 8], eax
adc [edi + 12], edx
pop edi
ret
qwmul endp
Division is the hardest one. I can't immediately recall an efficient division, maybe someone else has something.
Note: functions that return 64-bit values return their low dword in eax, and the high dword in edx.
Wow, these so need to be in macros.asm. Here is a little something for qw -> dw, thanks to f0dder.
qw2dw macro src:qword, dst:dword
fld [src]
fistp [dst]
endm
Hope this helps, Ehtyar.
Ehtyar, the macro you gave is a 64-bit floating point to 32-bit integer conversion. If you want to convert from 64-bit to 32-bit, you can simply 'forget' the high part. (of course, the number must not be too large)
Oh see i thought that was the case, lol. Guess i misunderstood f0dder when he explained, i don't know much about the fpu :red. Anyway, might we consider making a collection of q-word functions like this?
Ehtyar.
Hi Dark Schneider,
Nice to see someone else also writing a "File Explorer" thingie. I too had done one some time back and required addition routine to show the total of the file sizes in the current directory.
One question though: Why do you require to add TWO qwords? All you really require in addition of two sets of doublewords and format the final double-word set to display (in say the status bar or something), right?
The high-dword and low-dword would be for each file from the WIN32_FINDDATA, right?
So basically the upper limit for this summation would be (4294967296 * 4294967296) bytes, right? (1.844674407370955162e+19)
Nice to know you are working on a "qword functions set" :U :U :thumbu :thumbu
Regards,
Shantanu
On another note:
The following was a funtion that was required by me. I don't know if the Win32API already has something equivalent. (I did stumble upon MulDiv and the likes, but couldn't find the exact thing that I required.
I needed it for a file splitting thing that I required! (How many pieces would be created if the filesize and the chunksize is known)
Note: I have written this post under a linux box and from memory (not verified), so please don't mind any obvious mistakes! :red :red hope there are none :bg :bg After going home I will fix it, if anything is missing)
;dwHigh::dwLow divided by dwDivisor.
;remainder returned in address of pdwRemainder, if pdwRemainder != NULL
;quotient returned in eax :)
CompleteDivision proc dwHigh:DWORD, dwLow:DWORD, dwDivisor:DWORD, pdwRemainder:LPDWORD
LOCAL dwQuotient:DWORD
push eax
push ebx
push edx
mov edx, dwHigh
mov eax, dwLow
mov ebx, dwDivisor
div ebx
;now remainder in edx and quotient in eax
mov dwQuotient, eax
mov ebx, pdwRemainder
.if ebx != 0
mov [ebx], edx
.endif
pop edx
pop ebx
pop eax
mov eax, dwQuotient
ret
CompleteDivision endp
Cheers,
Shantanu
Thanks everyone :U
Quote from: Stan Hebben on January 19, 2007, 10:11:39 AM
; eax:edx = eax:edx + srclow:srchigh
qwadd macro srclow:req, srchigh:req
add eax, srclow
adc eax, srchigh
endm
; eax:edx = eax:edx - srclow:srchigh
qwsub macro srclow:req, srchigh:req
sub eax, srclow
subb eax, srchigh
endm
Shouldn't that be
; eax:edx = eax:edx + srclow:srchigh
qwadd macro srclow:req, srchigh:req
add
edx, srclow
adc eax, srchigh
endm
; eax:edx = eax:edx - srclow:srchigh
qwsub macro srclow:req, srchigh:req
sub
edx, srclow
sbb eax, srchigh
endm
Also, I think that using EDX:EAX would be better - it seems to be a convention to have EDX as the high 32-bits.
And how to convert a QWORD integer to ASCII string and back?
I used to adapted 'dq2ascii' function coded by someone I can't remember and it works on Windows ME but not on XP.
And again my own code is too slow to be useful.
Hi Dark Schneider,
What I had done was, write a "String Maths" library; add, sub, mul, div, etc for strings. Amongst all the functions, it had these
DwordToDecimalString PROTO :DWORD,:LPTSTR
QwordToString PROTO :DWORD,:DWORD,:LPTSTR
This QwordToString would convert the highdword to string, multiply it with the string "4294967296" and add the low dword to it. :bg
The only reason for this was to _somehow_ use only 32bit stuff and get it done; I am sure there would a "nicer" way to do it!
I am going to post the library code, but never got around to cleaning up the code. :red :'( :'(
Will do that and then post it!
Anyway, hope the algorithm helps for now,
Shantanu
Thank you, Shantanu Gadgil.
That's almost exactly what I had in mind (String Math) but my code is too slow.
Someone may have a better approach?
You may want to try my proc to convert signed qwords to ascii. See attached file. It covers the range of (-2^63) to (+2^63-1). (I've also sent it to hutch for evaluation and comparison with other available procedures.)
If your string representation contains a maximum of 18 digits (i.e. <10^18, i.e. less than 1,000,000,000 Gigs), I could also supply a procedure to convert such strings to a qword based on a similar approach using in part some FPU instructions.
Raymond
[attachment deleted by admin]
Thank you, raymond.
I will look into it when I return to my home next month.
Quote from: sinsi on January 20, 2007, 06:05:00 AM
Shouldn't that be
; eax:edx = eax:edx + srclow:srchigh
qwadd macro srclow:req, srchigh:req
add edx, srclow
adc eax, srchigh
endm
; eax:edx = eax:edx - srclow:srchigh
qwsub macro srclow:req, srchigh:req
sub edx, srclow
sbb eax, srchigh
endm
Also, I think that using EDX:EAX would be better - it seems to be a convention to have EDX as the high 32-bits.
You're right - on both points.
; edx:eax = edx:eax + srchigh:srclow
qwadd macro srclow:req, srchigh:req
add eax, srclow
adc edx, srchigh
endm
; edx:eax = edx:eax - srchigh:srclow
qwsub macro srclow:req, srchigh:req
sub eax, srclow
sbb edx, srchigh
endm