The MASM Forum

Microsoft 64 bit MASM => Examples => Topic started by: hutch-- on June 25, 2019, 04:53:27 PM

Title: Fast disk write example.
Post by: hutch-- on June 25, 2019, 04:53:27 PM
There were some advantages in working with the encryption examples, a good technique for very fast disk writes.

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

    ; This example is how to use an operating system process for very fast file output
    ; by using the file mapping technique, you write directly to the system paging file
    ; which in this context is limited to the amount of available memory installed on
    ; the computer. It allows you to write very large files to disk in a method that is
    ; much faster than normal file IO as it saves you the time taken to write memory to
    ; disk after allocated memory has been processed.

    ; It comes with some limitations, the requested memory must always be less than the
    ; available memory at the time of making the request. If more memory is requested
    ; than is available, the operating system will lock up and will require a hardware
    ; reset to restart the computer.

    ; There is a technique that is beyond the scope of this example where you create the
    ; file mapping and use a sliding window with MapViewOfFile() that is less than the
    ; amount of available memory and keep changing the MapViewOfFile() address.

    ; In most instances this sliding window technique is not needed as very large files
    ; are not commonly used and for normal sized files, the example will do the job with
    ; no problems.

    ; There is another consideration, this example unmaps the file and leaves the final
    ; output to the operating system through a method called "lazy write" and while the
    ; operating system lazy writes the data to disk, less memory is available while the
    ; lazy write is taking place.

    ; This example is protected from requesting more memory than is available.

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

    include \masm32\include64\masm64rt.inc

    IFNDEF MEMORYSTATUSEX
      MEMORYSTATUSEX STRUCT 16
        dwLength dd ?
        dwMemoryLoad dd ?
        ullTotalPhys dq ?
        ullAvailPhys dq ?
        ullTotalPageFile dq ?
        ullAvailPageFile dq ?
        ullTotalVirtual dq ?
        ullAvailVirtual dq ?
        ullAvailExtendedVirtual dq ?
      MEMORYSTATUSEX ENDS
    ENDIF

    .code

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

entry_point proc

    USING r12
    LOCAL pMMF  :QWORD                                      ; mapped file pointer
    LOCAL hMMF  :QWORD                                      ; mapped handle
    LOCAL hFile :QWORD                                      ; open file handle
    LOCAL bcnt  :QWORD                                      ; size of mapped file
    LOCAL mstat :QWORD

    SaveRegs

    mov rax, 1024*1024*1024*2                               ; load immediate into register
    mov bcnt, rax                                           ; store register into variable

  ; ********************************************************
  ; Protection from requesting more memory than is available
  ; ********************************************************
    mov mstat, rvcall(GetAvailableMemoryStatus)             ; get current available memory
    .If bcnt gt mstat
      conout "Request exceeds available memory",lf
      RestoreRegs
      .exit
    .EndIf
  ; ********************************************************

    mov hFile, flcreate("testfile.txt")                     ; create a test file
    invoke OpenMappedFile,hFile,"testfile", \
                          bcnt,ADDR pMMF,ADDR hMMF          ; map the open file

  ; *********************************************************
  ;       perform required task for file output here
  ; *********************************************************

    conout "Mapped file opened at ",str$(bcnt)," bytes",lf  ; display the mapped file size
    waitkey                                                 ; pause so you can see the result

  ; *********************************************************

    rcall CloseMappedFile,pMMF,hMMF                         ; close the file mapping
    flclose hFile                                           ; close the open file

    RestoreRegs
    .exit

entry_point endp

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

OpenMappedFile proc hFile:QWORD,lpName:QWORD,bcnt:QWORD,pHandle:QWORD,pMemory:QWORD

    LOCAL hi32  :DWORD
    LOCAL lo32  :DWORD

    mov lo32, r8d                               ; split hi and lo DWORDS of bcnt
    rol r8, 32
    mov hi32, r8d

    invoke CreateFileMapping, \
           hFile, \                             ; open file handle
           NULL, \
           PAGE_READWRITE, \                    ; read write access to memory
           hi32, \                              ; high DWORD of bcnt
           lo32, \                              ; low DWORD of bcnt
           lpName                               ; set file object name here

    mov rdx, rax                                ; MMF handle in RDX
    mov rcx, pHandle                            ; address of variable in RCX
    mov [rcx], rax                              ; write MMF handle to variable

    invoke MapViewOfFile, \
           rdx, FILE_MAP_WRITE,0,0,0
    mov rcx, pMemory                            ; address of variable in RCX
    mov [rcx], rax                              ; write start address to variable

    ret

OpenMappedFile endp

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

CloseMappedFile proc fmem:QWORD,hmem:QWORD
  ; ----------------------------------------
  ; unmapping the file first means you don't
  ; have to wait for the Windows lazy write.
  ; ----------------------------------------
    rcall UnmapViewOfFile,fmem                  ; unmap file
    rcall CloseMMF,fmem,hmem                    ; close the file mapping

    ret

CloseMappedFile endp

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

GetAvailableMemoryStatus proc

    LOCAL mse   :MEMORYSTATUSEX

    mov mse.dwLength, SIZEOF MEMORYSTATUSEX             ; initialise length
    invoke GlobalMemoryStatusEx,ADDR mse                ; call API

    mov rax, mse.ullAvailPhys                           ; return available memory

    ret

GetAvailableMemoryStatus endp

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

    end