News:

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

decimal as KiB,Mib,GiB etc.

Started by sinsi, July 29, 2008, 12:38:02 PM

Previous topic - Next topic

jj2007

Quote from: sinsi on August 01, 2008, 01:43:42 PM
jj, I'm thinking that if you want to use 'qw1a dq 1023' as a real8, it needs to be 'qw1a dq 1023.0'

Actually, I thought of a 64-bit integer, not a Real8, but that is apparently not possible.
I get the impression, though, that this could be done very elegantly with the MMX instructions, using this logic:
  ; move the number into mm0
  movq mm0, QWORD ptr [pNum]
  ; move a copy to mm1
  movq mm1, mm0
  ; put the "divisor" into mm2, and let it start with 1
  xor ecx, ecx
  inc ecx
  movd mm2, ecx
  ; loop
  .While mm0>=mm2  ; original value bigger or equal divisor?
     psllq mm2, 10      ; multiply divisor by 1024
     pslrq mm1, 10     ; divide number by 1024
     inc Counter         ; choose the next higher unit
  .Endw
  movd eax, mm1    ; the remainder
  invoke dwtoa, ....
This way, we would avoid these problems. However, I am stuck with the part in red: There is no simple way to compare mmx registers, apparently. Any help from our mmx freaks?

FORTRANS

jj2007 wrote:

QuoteMaybe related: Is there a correct way to convince the FPU that we are working with unsigned CPU registers?

Code:
  push eax ; our number, either high or low dword
  fild dword ptr [esp] ; move into ST (0)

  .if signed eax<0 ; if eax==C000000,
fabs ; the FPU thinks it's negative...

   The FPU only understands signed numbers (Otherwise
entering a negative number would be a pain).

   If you load 0FFFFFFFFH and do an FABS you
will get one.  Probably not what you want if
you are trying to use unsigned numbers.

   Two ways come to mind to get around that.
One, divide by 2, load, .multiply by 2, and add
one if the original was odd.

Two, mask off the high bit, load, load 080000000H
FABS, and FADD.  I think that works.  You can
generate the constant in other ways of course.

Regards,

Steve N.

jj2007

Thanks, Steve - much appreciated. The problem seems to occur earlier, however, when I try to load low and high dword separately. Switching to MMX seems really a lot more elegant; but the compare is somewhat complex.

qWord

Quote from: jj2007 on August 01, 2008, 02:53:38 PM
However, I am stuck with the part in red: There is no simple way to compare mmx registers, apparently.

by using sse2 ::)  it could be easy




;works only with unsigned values
;mm0>=mm2
psubq mm0,mm2
pextrw eax,mm0,3
test eax,08000h
.if !ZERO?      ;negativ result
    ;mm2 > mm0
.else           ;positiv result
    ;mm2 <= mm0
.endif


Do you want to replace bsr? it isn't as slow as you think => take a look in intels optimization reference manual (Appendix C).
FPU in a trice: SmplMath
It's that simple!

FORTRANS

jj2007 wrote:

QuoteThe problem seems to occur earlier, however, when I try to load low and high dword separately.

   Load low DWORD, load high DWORD, load 000001000H,
load ST(0), FMUL, FMUL, and FADD?  Or am I completely
off track?

HTH,

Steve N.

FORTRANS

   Arrh, 000010000H.  Bad eyes.

HTH,

Steve N.

jj2007

Quote from: qWord on August 01, 2008, 07:16:55 PM
by using sse2 ::)  it could be easy

Hutch, could you please post the sse2 macros? The old fourm is unavailable. I need pslrq and psubq
Thanks, jj

qWord

Quote from: jj2007 on August 01, 2008, 09:32:21 PM
Hutch, could you please post the sse2 macros? The old fourm is unavailable. I need pslrq and psubq

http://www.masm32.com/board/index.php?topic=973.0
FPU in a trice: SmplMath
It's that simple!

jj2007

Thanks for the link, but no luck. Here is the complete sse2.inc - pslrq and psubq are missing, unfortunately. Lingo once used
  db 0fh, 0fbh, 0d9h         ; psubq mm3, mm1
... where from?

;SSE2 macros for MASM 6.14 by daydreamer aka Magnus Svensson

ADDPD MACRO M1,M2
    db 066h
    ADDPS M1,M2
ENDM

ADDSD MACRO M1,M2
    DB 0F2H
    ADDPS M1,M2
ENDM

ANDPD MACRO M1,M2
    DB 066H
    ANDPS M1,M2
ENDM

ANDNPD MACRO M1,M2
    DB 066H
    ANDNPS M1,M2
ENDM

ORPD MACRO M1,M2
    DB 066H
    ORPS MACRO M1,M2
ENDM

XORPD MACRO M1,M2
    DB 066H
    XORPS M1,M2
ENDM

SUBPD MACRO M1,M2
    DB 066H
    SUBPS M1,M2
ENDM

SUBSD MACRO M1,M2
    DB 0F2H
    SUBPS M1,M2
ENDM

MULPD MACRO M1,M2
    DB 066H
    MULPS M1,M2
ENDM

MULSD MACRO M1,M2
    DB 0F2H
    MULPS M1,M2
ENDM

DIVPD MACRO M1,M2
    DB 066H
    DIVPS M1,M2
ENDM

DIVSD MACRO M1,M2
    DB 0F2H
    DIVPS M1,M2
ENDM

RCPPD MACRO M1,M2
DB 066H
    RCPPS M1,M2
ENDM

RCPSD MACRO M1,M2
    DB 0F2H
    RCPPS M1,M2
ENDM

RSQRTPD MACRO M1,M2
    DB 066H
    RSQRTPS M1,M2
ENDM

RSQRTSD MACRO M1,M2
    DB 0F2H
    RSQRTPS M1,M2
ENDM

SQRTPD MACRO M1,M2
    DB 066H
    SQRTPS M1,M2
ENDM

SQRTSD MACRO M1,M2
    DB 0F2H
    SQRTPS M1,M2
ENDM   

MAXPD   MACRO M1,M2
    DB 066H
    MAXPS M1,M2
ENDM

MAXSD MACRO M1,M2
    DB 0F2H
    MAXPS M1,M2
ENDM

MINPD MACRO M1,M2
    DB 066H
    MINPS M1,M2
ENDM

MINSD MACRO M1,M2
    DB 0F2H
    MINPS M1,M2
ENDM

MOVAPD MACRO M1,M2
    DB 066H
    MOVAPS M1,M2
ENDM

MOVHLSPD MACRO M1,M2
    DB 066H
    MOVHLSPS M1,M2
ENDM

MOVHPD MACRO M1,M2
    DB 066H
    MOVHPS M1,M2
ENDM

MOVLPD MACRO M1,M2
    DB 066H
    MOVLPS M1,M2
ENDM

MOVNTPD MACRO M1,M2
    DB 066H
    MOVNTPS M1,M2
ENDM

MOVUPD MACRO M1,M2
    DB 066H
    MOVUPS M1,M2
ENDM

CMPPD MACRO M1,M2,M3
    DB 066H
    CMPPS M1,M2,M3
ENDM

CMPSD MACRO M1,M2,M3
    DB 0F2H
    CMPPS M1,M2,M3
ENDM

CMPEQPD MACRO M1,M2
    DB 066H
    CMPEQPS M1,M2
ENDM

CMPEQSD MACRO M1,M2
    DB 0F2H
    CMPEQPS M1,M2
ENDM

CMPLTPD MACRO M1,M2
    DB 066H
    CMPLTPS M1,M2
ENDM

CMPLTSD MACRO M1,M2
    DB 0F2H
    CMPLTPS M1,M2
END

CMPLEPD MACRO M1,M2
    DB 066H
    CMPLEPS M1,M2
ENDM

CMPLESD MACRO M1,M2
    DB 0F2H
    CMPLEPS M1,M2
ENDM

CMPUNORDPD MACRO M1,M2
    DB 066H
    CMPUNORDPS M1,M2
ENDM

CMPUNORDSD MACRO M1,M2
    DB 0F2H
    CMPUNORDPS M1,M2
ENDM

CMPNEQPD MACRO M1,M2
    DB 066H
    CMPNEQPS M1,M2
ENDM

CMPNEQSD MACRO M1,M2
    DB 0F2H
    CMPNEQPS M1,M2
ENDM

CMPNLTPD MACRO M1,M2
    DB 066H
    CMPNLTPS M1,M2
ENDM

CMPNLTSD MACRO M1,M2
    DB 0F2H
    CMPNLTPS M1,M2
ENDM

CMPNLEPD MACRO M1,M2
    DB 066H
    CMPNLEPS M1,M2
ENDM

CMPNLESD MACRO M1,M2
    DB 0F2H
    CMPNLEPS M1,M2
ENDM

CMPORDPD MACRO M1,M2
    DB 066H
    CMPORDPS M1,M2
ENDM

CMPORDSD MACRO M1,M2
    DB 0F2H
    CMPORDPS M1,M2
    ENDM

jj2007

First problem solved:

This one I found by misusing OllyDbg:
   db 0fh, 0fbh, 0d8h         ; psubq mm3, mm0

... and this one was simply a typo, sorry :red
   psrlq mm1, 10            ; divide number by 1024

Now it assembles fine and starts throwing runtime errors  :green

jj2007

#25
OK, it's time for some testing... code attached in next post.

0       bytes   AUTOEXEC.BAT
211     bytes   boot.ini
4.83    kB      Bootfont.bin
0       bytes   CDS
0       bytes   CONFIG.SYS
0       bytes   db_circs
0       bytes   Documents and Settings
1015.42 MB      hiberfil.sys
0       bytes   IO.SYS
0       bytes   MSDOS.SYS
0       bytes   MSOCache
46.44   kB      NTDETECT.COM
245.18  kB      ntldr
756.00  MB      pagefile.sys
0       bytes   Programmi
0       bytes   RECYCLER
0       bytes   System Volume Information
0       bytes   WINDOWS

jj2007

#26
Quote from: sinsi on August 01, 2008, 01:43:42 PM
PS sorry jj, your love of the 'xxx$()' macro is for you to do... :bg

Your wish is my command:

   invoke GetCurrentDirectory, 260, offset buffer
   invoke lstrcat, offset buffer, chr$("\*.*")
   invoke FindFirstFile, offset buffer, addr wfd
   mov fHandle, eax
   mov ecx, offset fSize         ; we need to store the file size elsewhere ...
   mov eax, wfd.nFileSizeHigh   ; ... because stupidly enough, the wfd order...
   mov [ecx+4], eax
   mov eax, wfd.nFileSizeLow   ; ... is wrong, so we have to invert it
   mov [ecx], eax

   print flexbyte$(ecx)      ; format [ecx] nicely: ecx is a pointer to a QWORD

Full code no longer attached here - see later post. The proc has become awfully long - 136 bytes. I hope Vista left some space on your harddisk  :green

FORTRANS

Hi,

   I found an error in the code I posted earlier.  Posted
a correction.  Sorry.  Output now looks like:

  490.58 GiB
    2.58 GiB
       0 Bytes
   1,023 Bytes
    1.00 KiB
   15.99 EiB
1,023.99 PiB


Regards,

Steve N.

Mirno

Please forgive my lateness on this - I saw the thread last week but didn't have a chance to post earlier...

You can achive the result you want with a single divide (it gives the modulo too - which is important).
You need to drive the whole thing off the exponent of a real4.

Pseudo code:
Take the expoent (bits 30 down to 23)
Subtract 127
Divide by 10
Add 127 to the remainder, and replace the exponent in the original number
The result of the division is 0 = bytes, 1 = kilobytes, 2 = megabytes etc.
Print the resulting floating point number (it will be in the range of 0 to 1023.999ish), and append some string pointed to by the result of the division.

Mirno

jj2007

Quote from: Mirno on August 04, 2008, 08:36:34 AM
Pseudo code:
Take the expoent (bits 30 down to 23)
Subtract 127
Divide by 10
Add 127 to the remainder, and replace the exponent in the original number
The result of the division is 0 = bytes, 1 = kilobytes, 2 = megabytes etc.

Looks interesting. I tried my luck but the result is not convincing. Any idea?

  .data
MyQword dq 12345678
MyReal4 REAL4 0.0
  .code
  int 3 ; let Olly say Hi
  mov esi, offset MyQword
  fild MyQword ; convert quad
  fst MyReal4 ; to real4

  mov ecx, offset MyReal4
  xor eax, eax ; not really needed
  mov al, [ecx+3] ; take the exponent
  and al, 127 ; mask out bit 31, i.e. take bits 30 down to 23
  sub al, 127 ; sub 127
  aam ; divide al by 10, result is in ah
  add ah, 127 ; add 127
  mov [ecx+3], ah ; replace the exponent
  fld MyReal4 ; show it in Olly