News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

QWORD related functions

Started by Dark Schneider, January 19, 2007, 06:50:04 AM

Previous topic - Next topic

Dark Schneider

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.  :(

stanhebben

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.

Ehtyar

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.

stanhebben

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)

Ehtyar

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.

Shantanu Gadgil

#5
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
To ret is human, to jmp divine!

Shantanu Gadgil

#6
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
To ret is human, to jmp divine!

Dark Schneider


sinsi

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.
Light travels faster than sound, that's why some people seem bright until you hear them.

Dark Schneider

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.

Shantanu Gadgil

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
To ret is human, to jmp divine!

Dark Schneider

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?

raymond

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]
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com

Dark Schneider

Thank you, raymond.

I will look into it when I return to my home next month.

stanhebben

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