News:

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

64 bit numbers with 32 bit asm

Started by someone, March 27, 2010, 06:53:32 AM

Previous topic - Next topic

someone

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

hutch--

Floating point would be fine and can handle larger than 64 bit (IE: 80 bit).
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

jj2007

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

.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)

someone

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


japheth

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


jj2007

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.

someone

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

jj2007

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

japheth

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
     


MichaelW

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
eschew obfuscation

hutch--

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.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

lingo

"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

donkey

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
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

lingo

"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

donkey

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
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable