The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: someone on March 27, 2010, 06:53:32 AM

Title: 64 bit numbers with 32 bit asm
Post by: someone on March 27, 2010, 06:53:32 AM
hi, i need some information on those large 64 bit numbers (2 dwords), the kind you see in file sizes

at the moment the two main things i need to do are addition and converting the number to text so it can be displayed to the user

so for the addition, how for example do i add 0FFFFFFFFFFh and 0FFFFFFFFFFh ( = 01FFFFFFFFFEh)
this is what i want:
dword value1_low = 0FFFFFFFFh
dword value1_high = 0FFh
dword value2_low = 0FFFFFFFFh
dword value2_high = 0FFh
dword result_low = 0FFFFFFFEh
dword result_high = 01FFh
i want unsigned addition, it's for file sizes (and because i hate signed numbers)

i would prefer to avoid floating point, but if it's more efficient then it doesn't matter, as long as it's unsigned and i can get a
full maximum value of 0FFFFFFFFFFFFFFFFh

as for the second thing, now how can i convert the number to a string, basically i need a function the same as dwtoa as
in the masm32 extra includes, something like a qwtoa, but i can't get that to work

(p.s. please don't just give me links to masses of information in other places to read, i have been looking into this
literally for years, and finally resorted to posting at a forum to ask, some simple code examples would be best)

thanks if you can help
Title: Re: 64 bit numbers with 32 bit asm
Post by: hutch-- on March 27, 2010, 07:54:05 AM
Floating point would be fine and can handle larger than 64 bit (IE: 80 bit).
Title: Re: 64 bit numbers with 32 bit asm
Post by: jj2007 on March 27, 2010, 08:14:04 AM
Quote from: someone on March 27, 2010, 06:53:32 AM
as for the second thing, now how can i convert the number to a string, basically i need a function the same as dwtoa as
in the masm32 extra includes, something like a qwtoa, but i can't get that to work

There are other ways to do it, but Str$() is fairly simple to use:
Quoteinclude \masm32\MasmBasic\MasmBasic.inc   ; get the library here (http://www.masm32.com/board/index.php?topic=12460)

.code
start:
   mov eax, 123456789   ; create a nice qword number
   mov ecx, eax
   mov edx, 1000000000
   mul edx
   Print Str$("edx::eax+ecx=%i\n\n", edx
::eax+ecx)
   inkey "Press any key"
   Exit
end start

Output:
edx::eax+ecx=123456789123456789

In its simplest form, you can use Print Str$("%i", edx::eax)
Title: Re: 64 bit numbers with 32 bit asm
Post by: someone on March 27, 2010, 08:31:38 AM
but how, i only know the basics of floating point, and so far can only do division, all the documents i have are too complicated and don't
explain the simple basic step by step process of adding two numbers, it must be unsigned too, which is another thing i'm not too sure about with fp

i kind of wanted to avoid floating point, only because i don't know enough about it, if i could get it too work any way, even with fp, it would be great

the main problem i have had so far with floating point is that i don't know how to get a 64 bit value (via two seperate dwords) pushed onto the floating
point stack, and then later popped off into the right seperate dwords

is there some (efficient) mathematical way of doing it (avoiding floating point), for example adding the high and low seperately then shifting the bits left
i know that wouldn't work, but something similar

once again this problem has plagued me for years and i want to get it sorted

------------------------------

thanks for the suggestion, but MasmBasic isn't what i'm looking for, for the string conversion, i just need a basic function (in code) that i can add to my
own code (something i can completely rewrite my own way), rather than a seperate library, better yet i would prefer just an explanation of the process
of converting a long value to a string, that way i can develop my own module

Title: Re: 64 bit numbers with 32 bit asm
Post by: japheth on March 27, 2010, 08:49:17 AM
You can use MSVCRT's (s)printf to render 64-bit numbers.

This example isn't written for Masm32, but I guess you'll get the idea:


;*** 64bit numbers

.386
.MODEL FLAT, stdcall
option casemap:none

.nolist
.nocref
WIN32_LEAN_AND_MEAN equ 1
include windows.inc
include stdio.inc
include macros.inc
.list
.cref

lf equ 10

.CODE

main proc c

local pMem:ptr byte

mov edx,12345678h
mov eax,0ABCDEF00h
invoke printf, CStr(<"EDX::EAX=%I64X",lf>),edx::eax

mov eax, 2000000000
mov edx, 32
mul edx
invoke printf, CStr(<"2000000000*32=%I64u",lf>),edx::eax
ret

main endp


mainCRTStartup proc c
call main
invoke ExitProcess, 0
mainCRTStartup endp

end mainCRTStartup



Here's the makefile. Note that MSVCRT.LIB is used!


name = testl

DEBUG=0
OUTDIR=RELEASE

LOPTD=
AOPTD=

ASM = jwasm -c -Sg -Fl$* -Fo$* -coff -I \win32inc\include -I\asm\inc $(AOPTD)
CLIB=msvcrt.lib
#CLIB=libc32.lib
LOPT=/OUT:$*.exe /MAP:$*.map /SUBSYSTEM:CONSOLE $(LOPTD) /FIXED:NO /LIBPATH:\win32inc\lib
LINK=link
MODS=$*.obj
LIBS=kernel32.lib $(CLIB)

$(OUTDIR)\$(name).exe: $*.obj $(name).mak
    $(LINK) $(MODS) $(LIBS) $(LOPT) /OUT:$*.exe

$(OUTDIR)\$(name).obj: $(name).asm $(name).mak
     $(ASM) $(name).asm

Title: Re: 64 bit numbers with 32 bit asm
Post by: jj2007 on March 27, 2010, 08:51:29 AM
Quote from: someone on March 27, 2010, 08:31:38 AM
the main problem i have had so far with floating point is that i don't know how to get a 64 bit value (via two seperate dwords) pushed onto the floating point stack
...
i just need a basic function (in code) that i can add to my own code (something i can completely rewrite my own way)

If you have difficulties for years to find out how to push a qword on the FPU, then inserting include \masm32\MasmBasic\MasmBasic.inc on top of your code, and using mov eax, Str$("%i", edx::eax) seems the most adequate solution.
Title: Re: 64 bit numbers with 32 bit asm
Post by: someone on March 27, 2010, 09:01:58 AM
once again, i don't want to add a large module of someone elses code to my apps, so i won't be using MasmBasic, sorry
and i like things to be pure asm, so i'd like to avoid the printf function, however it is viable, and if i can't find a solution
for the string conversion i might consider printf as a last resort, again thanks for your suggestions, still not the answers
i'm looking for, i really want to get the addition problem solved
Title: Re: 64 bit numbers with 32 bit asm
Post by: jj2007 on March 27, 2010, 09:15:23 AM
> the main problem i have had so far with floating point is that i don't know how to get a 64 bit value (via two seperate dwords) pushed onto the floating point stack, and then later popped off into the right seperate dwords

My apologies that I suggested Basic. Let's go for a compromise: Once you have learned "how to get a 64 bit value (via two seperate dwords) pushed onto the floating point stack, and then later popped off into the right seperate dwords", I will point you to drizz' qword to Ascii routine (part of the Basic), so that you can "completely rewrite" it your own way.
Title: Re: 64 bit numbers with 32 bit asm
Post by: japheth on March 27, 2010, 09:53:26 AM
Quote from: someone on March 27, 2010, 09:01:58 AM
... i really want to get the addition problem solved

the "addition problem" is none - or, more exactly, it's a question for the campus:



v1 dq 0ffffffffffh
v2 dq 0ffffffffffh

   mov eax,dword ptr v1+0
   mov edx,dword ptr v1+4
   add eax,dword ptr v2+0
   adc edx,dword ptr v2+4
     

Title: Re: 64 bit numbers with 32 bit asm
Post by: MichaelW on March 27, 2010, 11:05:27 AM
someone,

The dwtoa procedure has been optimized for speed, and that tends to make the code much harder to understand. If you are having problems with this, then you should start with simple, easy to understand code.

In japheth's example above the ADD instruction adds the low-order dwords and leaves any overflow in the carry flag. The ADC instruction adds the high-order dwords, and adds in the value of the carry flag.

You could load the 64-bit integers into the FPU, do the addition, and store the result in v2 (or where ever) with just four instructions:

fild v1     ; ST(0)=v1
fild v2     ; ST(0)=v2, ST(1)=v1
fadd        ; ST(0)=sum, ST(1)-ST(7) empty
fistp v2    ; store result to memory and pop, leaving ST(0)-ST(7) empty


Your example values are in hex, so I'll assume that you wish to display in hex. Note that in a hex string each hex digit represents the value of one 4-bit nibble. Knowing this, a value can be converted to a hex string by decomposing the value into nibbles and using the value of each nibble as an index into a table of hex digits. The data could be defined like this:


    .data
        v1        dq 0FFFFFFFFFFh
        v2        dq 0FFFFFFFFFFh
        buffer    db 16 dup(0),0
        hexDigits db "0123456789ABCDEF"


And assuming that the result were stored in v2, the code to set up the conversion and convert the low-order DWORD only could be like this:

    mov edx, DWORD PTR v2     ; copy low-order dword of result to EDX
    mov edi, OFFSET buffer
    add edi, 15               ; set EDI to end of buffer
    mov ecx, 8                ; load digit counter
  @@:
    mov ebx, edx              ; copy value to EBX
    and ebx, 0Fh              ; mask off all but lower nibble
    mov al, hexDigits[ebx]    ; get the corresponding hex digit
    mov [edi], al             ; store it in the buffer
    shr edx, 4                ; shift next nibble into position
    dec edi                   ; adjust EDI for next digit
    dec ecx
    jnz @B                    ; loop if digit counter not zero


And instead of trying to simultaneously debug the conversion code and the display code, I would at least start out using the CRT printf procedure to display the values:

invoke crt_printf, cfm$("%I64x\n"), v2
Title: Re: 64 bit numbers with 32 bit asm
Post by: hutch-- on March 27, 2010, 12:31:54 PM
someone,

There is some wisdom in what you have been told in that there are a number of examples that you can clearly look at and learn how they are done. JJ has written code that will do the conversion, the MASM32 library has bits that should be able to help you, Japheth has made suggestions that can help you and Michael has shown you how to use the simplest method in floating point to do the job.

Coming from a large range of people who have written assembler for years, the best way to fail is to take on too many things that you don't know how to do and among the things you are trying to do is write a runtime library and that is not a beginners task. Lay out you task in bits to get it going using anything you can to make it work then rewrite each part your own way. A runtime library is in fact written in bits and when you have enough bits you can perform more complex tasks.
Title: Re: 64 bit numbers with 32 bit asm
Post by: lingo on March 27, 2010, 12:57:18 PM
"as for the second thing, now how can i convert the number to a string, basically i need a function the same as dwtoa as
in the masm32 extra includes, something like a qwtoa, but i can't get that to work"


just download b2a3264.zip  from http://www.masm32.com/board/index.php?topic=8974.45  :wink
Title: Re: 64 bit numbers with 32 bit asm
Post by: donkey on March 27, 2010, 01:28:43 PM
For the second part, I usually use The Svin's qword to ascii routine:

qw2a PROC uses ebx esi edi pqwValue:DWORD,lpBuffer:DWORD
LOCAL qtemp :QWORD
LOCAL qstore :QWORD

; The Svin

movq [qstore],mm7
emms

mov esi,[pqwValue]
mov edi,[lpBuffer]
mov edx,[esi]
mov eax,[esi+4]

cmp eax,0DE0B6B3h
jc  C1
jne C2
cmp edx,0A7640000h
jc  C1
C2:
cmp eax,8AC72304h
jc  D1
jne D2
cmp edx,89E80000h
jc  D1
D2:
mov BYTE PTR [edi],'1'
sub edx,89E80000h
lea edi,[edi+1]
sbb eax,8AC72304h

D1:
mov BYTE PTR [edi],'/'
@@:
inc BYTE PTR [edi]
sub edx,0A7640000h
sbb eax,0DE0B6B3h
jnc @B
add edx,0A7640000h
adc eax,0DE0B6B3h
inc edi

C1:
mov DWORD PTR [qtemp],edx
mov DWORD PTR [qtemp+4],eax

sub esp,10
fild QWORD PTR [qtemp]
fbstp TBYTE PTR [esp]
xor esi,esi
@@:
pop eax
bswap eax
mov ebx,eax  

mov ecx,eax
mov bl,bh

shr ecx,16
mov ah,al

shr bl,4
shr al,4

and bh,0fh
and ah,0fh

shl ebx,16
and eax,0FFFFh

mov edx,ecx
mov cl,ch

mov dh,dl
shr cl,4

shr dl,4
and ch,0fh

and dh,0fh
shl ecx,16

lea eax,[eax+ebx+30303030h]
lea edx,[edx+ecx+30303030h]

mov [edi+10],eax
mov [edi+14],edx
xor esi,1
lea edi,[edi-8]
jne @B

mov ah,[esp]
add edi,16
mov al,ah
add esp,2
shr  al,4
mov esi,[lpBuffer]
and eax,0f0fh
or eax,3030h
mov [edi],ax
cmp edi,esi
mov BYTE PTR [edi+18],0
jne P1
mov ecx,-20
add edi,19
@@:
inc ecx
cmp BYTE PTR [edi+ecx],30h
je @B
mov eax,ecx
js Z0
neg eax
add esi,eax
@@:
mov al,[edi+ecx]
mov [esi+ecx],al
inc ecx
jne @B

P1:
movq mm7,[qstore]
emms
ret
Z0: 
mov BYTE PTR [esi+1],0
jmp P1
qw2a endp
Title: Re: 64 bit numbers with 32 bit asm
Post by: lingo on March 27, 2010, 02:15:26 PM
"I usually use The Svin's qword to ascii routine"

Really? :wink
Would you be so kind to explain the meaning of the register mm7 and the local variable qstore?
What do you think about MCoder's optimization here: http://www.asmcommunity.net/board/index.php?topic=5197.15
Title: Re: 64 bit numbers with 32 bit asm
Post by: donkey on March 27, 2010, 03:57:37 PM
Hey Lingo,

I didn't write it, you could ask The Svin, he obviously had some reason to preserve the register, I never bothered to remove it.

Edgar
Title: Re: 64 bit numbers with 32 bit asm
Post by: donkey on March 27, 2010, 04:43:06 PM
Quote from: lingo on March 27, 2010, 02:15:26 PM
What do you think about MCoder's optimization here: http://www.asmcommunity.net/board/index.php?topic=5197.15

Nice, I have used the Svin's routine as a copy and paste for many years, probably since I first started in assembly, never saw any reason to change it or even look for a better solution as it worked and was more than enough for my purposes. Also there are exceedingly few times I ever need to convert qwords to ascii, I could probably count the number of times I needed one in the last 8 years on one hand...
Title: Re: 64 bit numbers with 32 bit asm
Post by: someone on March 27, 2010, 10:11:13 PM
ok thank you very much everybody the problems are solved now

special thanks to japeth, that was exactly the answer i was looking for, i didn't know about adc
here's my proc for those interested:

Add64Bit proc lpQwordOut:DWORD, dwInValueToAddHigh:DWORD, dwInValueToAddLow:DWORD
   mov ecx, lpQwordOut
   mov eax, dwInValueToAddLow
   mov edx, dwInValueToAddHigh
   add dword ptr [ecx], eax
   adc dword ptr [ecx+4], edx
   ret
Add64Bit endp

and also special thanks to donkey for the qw2a proc, that's also exactly what i was looking for, although
it's strange in the code that mm7 is preserved, anyway i'll remove that, and also avoid using bswap
to keep it with 386

also thanks to MichaelW for the floating point point example, it's so simple, i'm sure i have tried that in the past
but it never worked for me, i must have missed something, probably because in my debugger the fpu register
shows a decimal value and that threw me off

i guess the next stage would be 96 bit values, but thats for another day

also on a side note, i'm no beginner at assembly programming, it's been my main programming language for at
least 7 years now, i have just avoided dealing with these small things, until now

thanks again to everybody

Title: Re: 64 bit numbers with 32 bit asm
Post by: Ghandi on March 28, 2010, 12:38:38 AM
Just wondering because i know nothing about this subject, when the ADC is performed would we then check to see that the total wasn't larger than 64 bits?

Example:

Num1 = F000000000000000
Num2 = 1000000000000000

Num1 + Num2 = 10000000000000000

Which is now a 72 bit number because it requires at least 9 bytes to store now, doesnt it? (68 bits if you allow nibbles instead of bytes)

HR,
Ghandi
Title: Re: 64 bit numbers with 32 bit asm
Post by: someone on March 28, 2010, 01:05:14 AM
yes you are right, you can check
for my situation, i'm relying on not ever needing a number larger than 64 bits, so there isn't much need
but adc still sets the next carry flag if the number goes over 64 bits, i think means that the addition can
go on as many times as you want it to, by basically just repeating the last two lines

here are my procedures for those interested, now i have one that adds 96 bit numbers as well
also they check if the result is too big, and if it is then it sets the result to the maximum FFFF...

Add64Bit proc lp64BitNumber:DWORD, dwAddValueHigh:DWORD, dwAddValueLow:DWORD
   mov ecx, lp64BitNumber
   mov eax, dwAddValueLow
   add dword ptr [ecx], eax
   mov eax, dwAddValueHigh
   adc dword ptr [ecx+4], eax
   jc @too_big
   ret
@too_big:      ;will jump here, if the result is bigger than a 64 bit number
   mov dword ptr [ecx], 0FFFFFFFFh
   mov dword ptr [ecx+4], 0FFFFFFFFh
   ret
Add64Bit endp

Add96Bit proc lp96BitNumber:DWORD, dwAddValueHighest:DWORD, dwAddValueHigh:DWORD, dwAddValueLow:DWORD
   mov ecx, lp96BitNumber
   mov eax, dwAddValueLow
   add dword ptr [ecx], eax
   mov eax, dwAddValueHigh
   adc dword ptr [ecx+4], eax
   mov eax, dwAddValueHighest
   adc dword ptr [ecx+8], eax
   jc @too_big
   ret
@too_big:      ;will jump here, if the result is bigger than a 64 bit number
   mov dword ptr [ecx], 0FFFFFFFFh
   mov dword ptr [ecx+4], 0FFFFFFFFh
   mov dword ptr [ecx+8], 0FFFFFFFFh
   ret
Add96Bit endp
Title: Re: 64 bit numbers with 32 bit asm
Post by: donkey on March 28, 2010, 04:32:49 AM
Quote from: lingo on March 27, 2010, 02:15:26 PM
"I usually use The Svin's qword to ascii routine"

Really? :wink
Would you be so kind to explain the meaning of the register mm7 and the local variable qstore?

Actually, going through some old old old code I found that it was me who added the preservation of mm7 because I needed it once and modified the function. After that I must have C&P'ed it from that program and it was viral at that point. So I can't blame that one on the Svin, it was my fault.
Title: Re: 64 bit numbers with 32 bit asm
Post by: raymond on March 28, 2010, 04:34:10 AM
someone,

Just in case you may want to learn a bit more, the latest version of the Fpulib contains two functions to convert qwords to ascii, one for unsigned and the other for signed qwords. Both are based on using multiplications instead of division to perform the conversion.

That latest version of the Fpulib also accepts qwords as input for many of the functions using the FPU.

AND, the source code of each function is included for your education in the downloadable file from:
http://www.ray.masmcode.com/fpu.html#fpulib

PLUS, if you ever want to learn how to program the FPU yourself, a tutorial explaining almost every aspect of using floats is available on the same page of the above link. You can browse it online or download the entire tutorial. Be sure to read and understand the first two chapters.