problem with this code.. rectangle size changing with SetBkColor

Started by Rainstorm, December 07, 2008, 12:54:19 PM

Previous topic - Next topic

Rainstorm

in the below code if one of the functions, SetBkColor or SetBkMode are uncommented, the size of the rectangle changes on its own & gets much larger. - don't know what am doing wrong here.
the code just uses a hatch brush to fill a rectangle
thanks !

    invoke GetDC, hwnd
    mov hdc, eax

    invoke CreateHatchBrush, HS_BDIAGONAL, 11009272
    mov h_hatch_brush, eax
    invoke SelectObject, hdc, h_hatch_brush
    mov hdefault_brush, eax
   
    mov rect_left, 150
    mov rect_top,   50

    mov ecx, 90                            ; width
    mov edx, 30                            ; height
    add ecx, rect_left
    add edx, rect_top
   
  comment ×
  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    create a rectangle & fill it using 'FillRect' and a Hatch Brush
  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ×
;   invoke SetBkColor, hdc, 11639171
;   invoke SetBkMode, hdc, TRANSPARENT
   
    invoke SetRect, addr rc_fill, rect_left, rect_top, ecx, edx   
    invoke FillRect, hdc, addr rc_fill, h_hatch_brush     ; hdc, prect, brush/color
    invoke SelectObject, hdc, hdefault_brush   ; select the defaultbrush back in the DC
    invoke DeleteObject, h_hatch_brush         ; delete the new brush

    invoke ReleaseDC, hwnd, hdc                ; release the DC


Rainstorm

figured it out.. i had added the SetBKColor lines later..& forgot they were before the SetRect function & destroying the ecx, edx registers used in SetRect ; P

jj2007

Quote from: Rainstorm on December 07, 2008, 01:18:41 PM
figured it out.. i had added the SetBKColor lines later..& forgot they were before the SetRect function & destroying the ecx, edx registers used in SetRect ; P

Ey ey ey, these naughty Win32 API's destroy everything! Here is one that leaves ecx and edx in peace:


SetRect32 PROTO: DWORD, :DWORD, :DWORD, :DWORD, :DWORD
...
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
SetRect32 proc ps_r:DWORD,left:DWORD,top:DWORD,right:DWORD,bottom:DWORD
pop eax ; trash the return address
pop eax ; move the first argument to eax
pop dword ptr [eax].RECT.left
pop dword ptr [eax].RECT.top
pop dword ptr [eax].RECT.right
pop dword ptr [eax].RECT.bottom
sub esp, 6*4 ; correct for 6 dword pops
ret 5*4 ; correct stack for five arguments, return ps_r in eax
SetRect32 endp
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef


19 bytes long, and on a Core2 25% faster than the original  :bg

SetRect32 11 cycles
SetRect 14 cycles


sinsi

Just a question, can a proc be interrupted and possibly have it's stack used?
That code could have been nasty in 16bit land if an INT happened, but not in win32 user code, right?
Light travels faster than sound, that's why some people seem bright until you hear them.

Tedd

Each thread has its own stack, so they don't interfere with each other (and interrupts are handled as a separate process too.)

Be careful re-using stack arguments this way though, if you call a function which modifies them in-place you're in for a treat.
No snowflake in an avalanche feels responsible.

jj2007

Quote from: Tedd on December 08, 2008, 11:51:32 AM

Be careful re-using stack arguments this way though, if you call a function which modifies them in-place you're in for a treat.


Can you give an example?

KeepingRealBusy

JJ,

Any time you access the callers parameters via ESP and not a static EBP, if you call another process and pass the original callers parameters, the INVOKE will be using an incrementing ESP as it pushes the original parameters (in reverse, last new parameter first). Doable, but watch out. The first new parameter will have the same ESP offset as your internal use, the next parameters will have to use an offset 4 larger than your internal use, then 8 larger, etc.

Dave.

jj2007

Quote from: KeepingRealBusy on December 08, 2008, 06:02:11 PM
JJ,

Any time you access the callers parameters via ESP and not a static EBP, if you call another process and pass the original callers parameters, the INVOKE will be using an incrementing ESP as it pushes the original parameters (in reverse, last new parameter first). Doable, but watch out. The first new parameter will have the same ESP offset as your internal use, the next parameters will have to use an offset 4 larger than your internal use, then 8 larger, etc.

Dave.

Correct. You can find a more explicit example in this thread.