News:

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

64 bit dialogbox, memory keeps raising up.

Started by FlySky, January 15, 2011, 02:31:32 PM

Previous topic - Next topic

FlySky

Hey guys,

I am having this DialogBox on which I have an DIBSection. The problem is that on 64 bit it keeps eating up memory. It keeps increasing the memory while no other programs are running. Compiling it 32 bit all works perfectly fine.
I've read that the PaintStruct and the Message structures are increased in size, but also that the window handle is now assumed to be a qword instead of a dword.

Consider the following code:

;this links in necessary imports
#Define LINKFILES

;comment this if building for 32bit
#Define WIN64

;windows.h which includes various other .h's
#Include "\GoAsm\include\windows.h"
#Include "\GoAsm\macros\Macros.asm"


;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Const Section

ScreenWidth    Equ 400
ScreenHeight   Equ 300
DialogAlign    Equ 600


;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Data Section
hInstance       DQ       ?
canvasDC        DQ      ?
canvasBmp       DQ      ?
hDC             DQ      ?
canvas_buffer   DQ      ?
clip1           DQ      ?
clip2           DQ      ?

;***************** structure to hold stuff from Windows on WM_PAINT (64-bit version)
PAINTSTRUCT STRUCT
            DQ 0      ;+0 hDC
            DD 0      ;+8 fErase
      left  DD 0      ;+C  left   )
       top  DD 0      ;+10 top    ) RECT
     right  DD 0      ;+14 right  )
    bottom  DD 0      ;+18 bottom )
            DD 0      ;+1C fRestore
            DD 0      ;+20 fIncUpdate
            DB 32 DUP 0   ;+24 rgbReserved
            DD 0      ;padding to bring total size to 72 bytes
ENDS

PS PAINTSTRUCT

canvas          BITMAPINFO  <>

;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DATA? Section



;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Code Section
START:

Invoke GetModuleHandle, 0
Mov [hInstance], Rax
Invoke DialogBoxParam, [hInstance], 101, 0, Offset WndProc, 0
Invoke ExitProcess, 0

WndProc Frame hWin, uMsg, wParam, lParam  --> I think a big problem lies here. It compiles saying that hWin is dword instead of Qword, how do I get it into a qword? same goes for wParam and lParam.

      Cmp D[uMsg], WM_INITDIALOG
      Jne > Wm_2
      Push DialogAlign
                                                               
           mov D[canvas.bmiHeader.biSize],sizeof BITMAPINFOHEADER
           mov D[canvas.bmiHeader.biWidth],ScreenWidth           
           mov D[canvas.bmiHeader.biHeight],-ScreenHeight       
           mov W[canvas.bmiHeader.biPlanes],1                   
           mov W[canvas.bmiHeader.biBitCount],32               
           Pop Rax                                             

             ; Setup DibSection.

                 Invoke GetDC, [hWin]                                                                      
                 Mov [hDC], Rax                                                                     
                 Invoke CreateCompatibleDC, Rax                                                         
                 Mov [canvasDC], Rax                                                                       
                 Invoke CreateDIBSection, [hDC], Offset canvas, DIB_RGB_COLORS, Offset canvas_buffer, 0, 0
                 Mov [canvasBmp], Rax                                                                      
                 Invoke SelectObject, [canvasDC], Rax                                                      
                 Invoke ReleaseDC, [hDC], 0                                                             
                                                                                                           
   Invoke SetTimer, [hWin], 1, 0, 0

Wm_2:
     Cmp D[uMsg], WM_TIMER
     Jnz > Wm_3
         
                                                                       
    Mov Rdi, [canvas_buffer]                                             
    Mov Rcx, ScreenWidth * ScreenHeight                                
    Xor Rax, Rax                                                       
    Rep Stosd                                                         
                                                                       
    ;--- drawing functions...                                            
                                                                         
    Mov Rdi, [canvas_buffer]                                            
                                                      
                                                      
   Invoke RedrawWindow, [hWin], 0, 0, RDW_INVALIDATE               

Wm_3:

   Cmp D[uMsg], WM_PAINT                                                                
    Jnz > Wm_4                                                                           
                                                                                       
     Mov Rax, [hWin]                                                                
   Mov Rcx, Offset PS                                                             
   Push Rcx                                                                        
   Push Rax                                                                        
   Invoke BeginPaint, Rax, Rcx                                                     
   Invoke BitBlt, Rax, 0, 0, ScreenWidth, ScreenHeight, [canvasDC], 0, 0, SRCCOPY
   Call EndPaint                                                                   

Wm_4:

      Cmp D[uMsg], WM_CLOSE                                 ; Did we press the close button
      Jne > Wm_5
      Invoke EndDialog, [hWin], 0

Wm_5:                                                               
   Cmp D[uMsg], WM_LBUTTONDOWN                                                           
   Jnz > Wm_6                                                                             
                                                                                         
      Invoke SendMessage, [hWin], WM_NCLBUTTONDOWN, HTCAPTION, NULL                      
                                                                                         
Wm_6:

   Xor Rax, Rax
   Ret

EndF

donkey

#1
   Cmp D[uMsg], WM_PAINT                                                               
    Jnz > Wm_4                                                                           
                                                                                       
     Mov Rax, [hWin]                                                               
   Mov Rcx, Offset PS                                                             
   Push Rcx                                                                       
   Push Rax                                                                       
   Invoke BeginPaint, Rax, Rcx                                                     
   Invoke BitBlt, Rax, 0, 0, ScreenWidth, ScreenHeight, [canvasDC], 0, 0, SRCCOPY
   Call EndPaint


The problem appears to be that you are not properly closing your BeginPaint which will lead to huge resource leaks. Win64 uses FASTCALL, when you push the parameters on the stack then later call EndPaint without parameters (because they are already on the stack) that is STDCALL. You must either mov them into the appropriate registers or pop them and use INVOKE. In FASTCALL the first two parameters are passed in ECX and EDX respectively so you could use those registers since you're already moving the data into registers (though the ones your using are not the correct ones and invoke is preferable).

   Cmp D[uMsg], WM_PAINT
    Jnz > Wm_4

   Mov Rcx, [hWin]
   Mov Rdx, Offset PS
   Push Rdx
   Push Rcx
   Call BeginPaint
   Invoke BitBlt, Rax, 0, 0, ScreenWidth, ScreenHeight, [canvasDC], 0, 0, SRCCOPY
   Pop Rcx
   Pop Rdx
   Call EndPaint


That said, you are always better off to use INVOKE, that way you don't have to deal with parameter order (which changes) or remember the registers used in FASTCALL.

   Cmp D[uMsg], WM_PAINT
    Jnz > Wm_4

   invoke BeginPaint, [hWin], Offset PS
   Invoke BitBlt, Rax, 0, 0, ScreenWidth, ScreenHeight, [canvasDC], 0, 0, SRCCOPY
   Invoke EndPaint, [hWin],Offset PS


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

donkey

As an addendum to this thread, I should also note that when you are translating WIN32 to WIN64 you must always make note of any CALL instruction and be sure to understand the code leading up to it. Since many WIN32 assembly programmers used parameters already on the stack to pass arguments to a CALL instruction as in the code above, you have to make sure you catch and rewrite those sequences. Also when writing WIN32 programs that you might later want to port to WIN64 you have to avoid this behavior. I am equally as guilty of the push/call method though I now try to avoid it like the plague. For a programming trick that has the potential of saving a microsecond of runtime, you can make the transition to 64 bit a living hell, the moral is ALWAYS USE INVOKE !, GoAsm will use the correct calling convention and even perform some optimization if applicable.
"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

FlySky

Many thanks for this lesson donkey. When I translated the 32 bit source, I totally forgot about win64 calling conventions. Thanks for the heads up.