News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Trouble with file length under Win64

Started by Gunther, February 10, 2021, 10:11:00 PM

Previous topic - Next topic

Vortex

Hi Gunther,

Reading this message :

http://masm32.com/board/index.php?topic=2769.msg29205#msg29205

Could you try the size prefixe %I64u ?

include     \masm32\include64\masm64rt.inc

EXTERN      ParseCmdLine:PROC

.data

msg1        db 'Size of the file %s = %I64u',13,10,0
msg2        db 'GetFileSize.exe filename.ext',13,10,0

.data?

cmdline     db 512 dup(?)

.code

start PROC

    call    main
    invoke  ExitProcess,0

start ENDP

main PROC

LOCAL .rsi:QWORD
LOCAL hFile:QWORD
LOCAL lpFileSizeHigh:QWORD

    mov     .rsi,rsi
    mov     rsi,OFFSET cmdline
    invoke  ParseCmdLine,rsi
    cmp     rax,2
    je      @f

    invoke  vc_printf,ADDR msg2
    ret
@@:   
    invoke  CreateFile,QWORD PTR [rsi+8],\
            GENERIC_READ,\
            0,0,OPEN_EXISTING,0,0

    mov     hFile,rax
   
    lea     rdx,lpFileSizeHigh
    invoke  GetFileSize,rax,rdx
   
    mov     rdx,lpFileSizeHigh
    shl     rdx,32
    add     rax,rdx
   
    invoke  vc_printf,ADDR msg1,\
            QWORD PTR [rsi+8],rax
           
    mov     rsi,.rsi
    ret

main ENDP

END


Gunther

Erol,

Quote from: Vortex on February 12, 2021, 04:22:23 AM
Could you try the size prefixe %I64u ?

yes, but it didn't work. Here is the output:

Value as unsigned long long = 5368717488
Value as long long          = 5368717488
Press any key to continue...

The source and EXE is attached in the zip archive.

Quote from: Vortex on February 12, 2021, 04:22:23 AM
Reading this message :

http://masm32.com/board/index.php?topic=2769.msg29205#msg29205

Interesting thread, by the way. Why didn't Jochen mention that one?

Gunther
You have to know the facts before you can distort them.

jj2007

Quote from: Gunther on February 12, 2021, 09:59:16 AM
Interesting thread, by the way. Why didn't Jochen mention that one?

> googling for "llu" format specifier "msvcrt.dll" reveals that it's a KnownBug in a KnownDLL ;-)

That's over 7 years ago, I can't remember all the times when we tortured the CRT :biggrin:


Vortex

Hi Gunther,

Replacing ADDR Value with only Value :

        invoke     vc_printf,ADDR uint64_format,Value     ;  ADDR Value
        invoke     vc_printf,ADDR str_format,ADDR NL

        ; print as long long

        invoke     vc_printf,ADDR str_format,ADDR msg1
        invoke     vc_printf,ADDR int64_format,Value      ; ADDR Value


Building and running the application :

Value as unsigned long long = 18446744073709551615
Value as long long          = -1
Press any key to continue...

TouEnMasm


a sample in 64:
Copy paste the full path of the file (console mode)


include sdk64.inc
include stdio.sdk
include conio.sdk

;https://docs.microsoft.com/en-us/windows/win32/secauthz/creating-a-security-descriptor-for-a-new-object-in-c--


;-c -nologo -coff -Zi4 -Zd
.LISTALL
.const
;------------------------------------MACROS--------------------------------------------------

PuPo MACRO M1,M2
Push M2
Pop M1
ENDM
PASSESPACETAB MACRO register
@@:
.if byte ptr [register] == " " || byte ptr [register] == 9
inc register
jmp @B
.endif
ENDM
;----------------------------------------------------------------------------------------------
.data
;--------------------------------------------------------------------------------------------------------------------
InfosFichiers WIN32_FIND_DATA <>
;key data

;--------------------------------------------
chaine db MAX_PATH dup(0)
szfile db MAX_PATH dup(0)
;-------------------------------------------------------------------------------------------------------------------
.code
include affiche_error_msg.inc
Import_File PROC FRAME
Local Hsearch:QWORD,retour:QWORD
mov retour,0
    invoke printf,TXT(" Copy paste the name of the file (full path) : ")
    invoke scanf,TXT("%s"),addr chaine
lea r11,chaine
PASSESPACETAB r11
invoke lstrcpy,addr szfile,R11
;test if the  file  exist and get the size
invoke FindFirstFile,addr szfile,addr InfosFichiers
          mov Hsearch,rax
.if rax != INVALID_HANDLE_VALUE
          invoke FindClose,Hsearch
mov retour,1
.endif
mov rax,retour
ret
Import_File endp

main proc ;c(32) or not c(64 fastcall) must be tested,not using main(standard entry crt) can need additionnal libraries
invoke Import_File
.if rax == 1
invoke printf,TXT(" Size of the file %u "),InfosFichiers.nFileSizeLow
.else
invoke printf,TXT(" File not found ")
.endif
invoke _getch

mov rax,0
ret
main endp

end

Fa is a musical note to play with CL

Gunther

Thanks Yves.
Quote from: TouEnMasm on February 12, 2021, 08:56:48 PM

a sample in 64:
Copy paste the full path of the file (console mode)

At the moment it is about the errors of the CRT when printing unsigned long long and long long.

Gunther
You have to know the facts before you can distort them.

Gunther

Erol,

Quote from: Vortex on February 12, 2021, 06:44:20 PM
Replacing ADDR Value with only Value :

that works fine. But that's a little strange, isn't it.

Jochen,

Quote from: jj2007 on February 12, 2021, 11:33:46 AM
> googling for "llu" format specifier "msvcrt.dll" reveals that it's a KnownBug in a KnownDLL ;-)

That's over 7 years ago, I can't remember all the times when we tortured the CRT :biggrin:

in other words, you're just like me - becoming forgetful. This is quite normal in old age.  :cool:

Gunther
You have to know the facts before you can distort them.

hutch--

I have not been following this topic in detail but here is a quick test piece that drops the correct number for a file larger than 4 gig.

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    include \masm32\include64\masm64rt.inc

    .code

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

entry_point proc

    LOCAL hFile :QWORD
    LOCAL flen  :QWORD
    LOCAL hiwd  :QWORD
    LOCAL lowd  :QWORD

    mov hFile, flopen("m:\$big\bigger.mp4")     ; 5,940,221,382 bytes

    invoke GetFileSize,hFile,ptr$(hiwd)
    mov flen, rax

    conout str$(flen),lf,lf
    conout str$(hiwd),lf,lf

    mov rax, flen
    mov rcx, 4294967296
    add rax, rcx                                ; add 4 gig

    conout str$(rax),lf

    flclose hFile

    waitkey
    .exit

entry_point endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    end

Gunther

Steve,

Quote from: hutch-- on February 12, 2021, 11:52:29 PM
I have not been following this topic in detail but here is a quick test piece that drops the correct number for a file larger than 4 gig.

yes, I've made a similar approach. conout (mighty macro) will do the job. Is it possible to print with conout long long integers, too?

Gunther 
You have to know the facts before you can distort them.

hutch--

Here is a PROC version that seems to work OK.

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    include \masm32\include64\masm64rt.inc

    .code

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

entry_point proc

    rcall LargeFileSize,"m:\$big\bigger.mp4"
    conout str$(rax),lf

    waitkey
    .exit

entry_point endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

LargeFileSize proc pName:QWORD

    USING r12
    LOCAL hFile :QWORD
    ; LOCAL flen  :QWORD
    LOCAL hiwd  :QWORD
    ; LOCAL lowd  :QWORD

    SaveRegs
    mov hFile, flopen(pName)

    invoke GetFileSize,hFile,ptr$(hiwd)
    cmp hiwd, 0
    je past

    mov rcx, 4294967296                         ; on the fly optimisation :)
  @@:
    add rax, rcx                                ; add 4 gig each iteration
    sub hiwd, 1
    jnz @B

  past:
    mov r12, rax                                ; preserve rax
    flclose hFile
    mov rax, r12                                ; restore rax
    RestoreRegs

    ret

LargeFileSize endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    end

TimoVJL

for big files and using long long
BOOL GetFileSizeEx(  HANDLE         hFile,  PLARGE_INTEGER lpFileSize);
May the source be with you

jj2007

Quote from: TimoVJL on February 13, 2021, 12:27:09 AM
for big files and using long long
BOOL GetFileSizeEx(  HANDLE         hFile,  PLARGE_INTEGER lpFileSize);

Good find :thumbsup:

However, some of the really big files are system files that CreateProcess can't handle, so FindFirst* is still the better choice...

Quote from: jj2007 on February 11, 2021, 12:48:08 AMGetFileSize is no good for certain hidden files (CreateFile fails), as I noted when testing for a large file:
include \masm32\MasmBasic\MasmBasic.inc
  Init
  .if Exist("C:\hiberfil.sys")
Inkey Str$("File size is %3f GB", edx::GfSize(-1)/1073741824)
  .else
Inkey "no such file"
  .endif
EndOfCode


File size is 4.39 GB (GfSize uses FindFirstFile instead of GetFileSize)

hutch--

 :biggrin:

Never could resist the temptation to optimise an algo.

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

LargeFileSize proc pName:QWORD

    USING r12, r13                              ; specify the registers to preserve
    LOCAL hiwd :QWORD                           ; allocate a LOCAL memory operand

    SaveRegs                                    ; save the regs specified in USING
    mov r13, flopen(pName)                      ; r13 is the file handle

    invoke GetFileSize,r13,ptr$(hiwd)
    cmp hiwd, 0                                 ; if hiwd = 0, bypass loop
    je past

    mov rcx, 4294967296                         ; load rcx with a 4 gig immediate
  @@:
    add rax, rcx                                ; add 4 gig each iteration
    sub hiwd, 1
    jnz @B

  past:
    mov r12, rax                                ; preserve rax
    flclose r13                                 ; close the file
    mov rax, r12                                ; restore rax
    RestoreRegs                                 ; restore the regs specified in USING

    ret

LargeFileSize endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤


Vortex

Hi Gunther,

There is nothing strange. You would like to print the value of the variable named Value not it's address. Disassembling the object module :

        lea     rcx, [str_format]                       
        lea     rdx, [msg0]                             
        call    qword ptr [__imp_printf]               
        lea     rcx, [uint64_format]                   
        mov     rdx, qword ptr [Value]                 
        call    qword ptr [__imp_printf]               
        lea     rcx, [str_format]                       
        lea     rdx, [NL]                               
        call    qword ptr [__imp_printf]               
        lea     rcx, [str_format]                       
        lea     rdx, [msg1]                             
        call    qword ptr [__imp_printf]               
        lea     rcx, [int64_format]                     
        mov     rdx, qword ptr [Value]                 
        call    qword ptr [__imp_printf]               
        lea     rcx, [str_format]                       
        lea     rdx, [NL]                               
        call    qword ptr [__imp_printf] 


Printing Value :

        invoke     vc_printf,ADDR uint64_format,Value

This will not work because it prints the address of the variable Value :

        invoke     vc_printf,ADDR uint64_format,ADDR Value

Gunther

Erol,

Quote from: Vortex on February 13, 2021, 12:49:53 AM
Printing Value :

        invoke     vc_printf,ADDR uint64_format,Value

This will not work because it prints the address of the variable Value :

        invoke     vc_printf,ADDR uint64_format,ADDR Value

you're right. It was my thought error.

Gunther
You have to know the facts before you can distort them.