The MASM Forum

Projects => MASM32 => Topic started by: frozen on August 05, 2020, 06:51:25 AM

Title: RECT Structure
Post by: frozen on August 05, 2020, 06:51:25 AM
Hi all,

I have a question regarding the RECT structure. If I understand correctly, the four values are defined as unsigned long in windows.inc (line 7624). However, the official documentation says that they should be signed long (https://docs.microsoft.com/en-us/windows/win32/api/windef/ns-windef-rect).

The issue I'm having is that GetWindowRect should return negative values for top and left when a window is maximized. However, due to the way the structure is defined, I'm getting top and left as huge positive numbers. As a workaround, I've created my own structure like this and it works fine.

MYRECT STRUCT
  left    SDWORD      ?
  top     SDWORD      ?
  right   SDWORD      ?
  bottom  SDWORD      ?
MYRECT ENDS

Since I'm still learning, I would like to know if this is a bug in windows.inc (very unlikely) or if I should have handled the negative values differently.

Thanks in advance!


Title: Re: RECT Structure
Post by: hutch-- on August 05, 2020, 07:54:02 AM
Hi frozen,

When it comes to a value being signed or unsigned, at the assembler level it is neither until its evaluated with conditional evaluation, mainly conditional jumps and some of the other instructions. While the DWORD / SDWORD distinction exists higher up that MASM handles with its pseudo high level constructs, neither a 32 bit register nor a 32 bit variable maintains that distinction, its just a bit pattern in the right sized storage.

Have a look at the conditional jumps list in the Intel manual or if you have it, a simpler reference and you will find complimentary pairs which have the distinction, just for example the distinction between the unsigned JA (jump if above) verses the signed JG (jump if greater).
Title: Re: RECT Structure
Post by: jj2007 on August 05, 2020, 08:43:03 AM
Code: [Select]
MYRECT STRUCT
  left    SDWORD      ?
  top     SDWORD      ?
  right   SDWORD      ?
  bottom  SDWORD      ?
MYRECT ENDS

This is what Hutch means - and it works regardless of "left" being DWORD or SDWORD:
Code: [Select]
cmp somerect.left, 0
jl itsnegative

However, to be fair, this works only with SDWORDs:
Code: [Select]
.if somerect.left<0
   ... do something for the negative case ...
.endif

With the existing Windows.inc version, you can use this workaround:
Code: [Select]
.if sdword ptr somerect.left<0
   ... do something for the negative case ...
.endif
Title: Re: RECT Structure
Post by: hutch-- on August 05, 2020, 09:11:05 AM
Knowing the distinction between JA verses JG allows you do a do a few tricks. If you have a finite number of ascending values as positive integers and you need to control the range, if you do the comparison with JA (the signed version) of say 0 to 10 with only one comparison,

  cmp var, 10
  ja errlbl

This works because with an unsigned compare, there are no negative number so you don't have to test for below zero. The high level notation is useful enough but learn your mnemonics (instructions) as they are more powerful and more flexible.
Title: Re: RECT Structure
Post by: TouEnMasm on August 05, 2020, 04:24:50 PM

The RECT structure is badly defined,she don't know  the x y coordinate (basic knowledge)
To avoid mistakes you can redefine it as follow.
Quote
   FRECT   STRUCT
      min POINT <>
      max POINT <>
   FRECT ENDS
;-------------------------------------------
POINT   STRUCT DEFALIGNMASM
   x DWORD ?
   y DWORD ?
POINT      ENDS

rect FRECT <>

then searching the lenght or the hight
       length = rect.max.X - rect.min.X      ;couldn't be negative even maximize
       Hight   = rect.max.Y - rect.min.Y      ;couldn't be negative even maximize



Title: Re: RECT Structure
Post by: hutch-- on August 05, 2020, 06:37:18 PM
This is not correct, a RECT structure is no more than 4 DWORD sized variables in a structure. If you only ever use it for a client area, then left and top are always zero but it can be used for many more things. Get a Window's co-ordinates and left and top are not zero.
Title: Re: RECT Structure
Post by: Vortex on August 05, 2020, 07:16:13 PM
Hi ToutEnMasm,

Hutch is right, here is how the structure is defined in windows.inc :

Code: [Select]
RECT STRUCT
  left    dd      ?
  top     dd      ?
  right   dd      ?
  bottom  dd      ?
RECT ENDS

The size of RECT is 16 bytes.
Title: Re: RECT Structure
Post by: TouEnMasm on August 05, 2020, 10:23:13 PM
WRONG!
Quote
POINT   STRUCT DEFALIGNMASM
   x DWORD ?
   y DWORD ?
POINT      ENDS
There is two points in the FSTRUCT I have given so 2+2=4 DWORD
The structure can replace the RECT structure in all API call.

Title: Re: RECT Structure
Post by: Vortex on August 05, 2020, 11:24:31 PM
Hi ToutEnMasm,

Code: [Select]
typedef struct tagRECT {
  LONG left;
  LONG top;
  LONG right;
  LONG bottom;
} RECT, *PRECT, *NPRECT, *LPRECT;

https://docs.microsoft.com/en-us/windows/win32/api/windef/ns-windef-rect

Retrieving the size of the structure ( 32-bit application ) :

Code: [Select]
#include <windows.h>
#include <stdio.h>

int main(void)
{
printf("sizeof(RECT)=%u\n",sizeof(RECT));
return 0;
}

Code: [Select]
sizeof(RECT)=16
Title: Re: RECT Structure
Post by: hutch-- on August 05, 2020, 11:32:52 PM
Yves,

One trick between a POINT struct and a RECT struct is you can use the address of a RECT struct as the target of a POINT API for the first two RECT members. What you are doing will work in some contexts but it is not a valid RECT structure.

If for example you do a GetWindowRect() rather than GetClientRect() you get the screen co-ordinates where with a GetClientRect() you only get the lower X Y. You use the two API calls to convert between the two. ScreenToClient() and ClientToScreen().

I would ask this much of you, when a new member asks a question and gets an answer, we don't need arguments about the details.
Title: Re: RECT Structure
Post by: TouEnMasm on August 06, 2020, 12:01:03 AM
The point was
Quote
This is not correct, a RECT structure is no more than 4 DWORD sized variables in a structure. If you only ever use it for a client area, then left and top are always zero but it can be used for many more things. Get a Window's co-ordinates and left and top are not zero.
I have corrected that,after if 16 bytes = 4 dword = 2 QWORD ,no matter
then if
Quote
If for example you do a GetWindowRect() rather than GetClientRect() you get the screen co-ordinates where with a GetClientRect() you only get the lower X Y. You use the two API calls to convert between the two. ScreenToClient() and ClientToScreen().
It is the same problem with the RECT structure than with the FRECT



Title: Re: RECT Structure
Post by: hutch-- on August 06, 2020, 12:43:52 AM
It is not a problem, its just knowing how the API functions work. Again, we do not need arguments when a new member asks a question.
Title: Re: RECT Structure
Post by: jj2007 on August 06, 2020, 12:58:21 AM
Code: [Select]
typedef struct tagRECT {
  LONG left;
  LONG top;
  LONG right;
  LONG bottom;
} RECT, *PRECT, *NPRECT, *LPRECT;

https://docs.microsoft.com/en-us/windows/win32/api/windef/ns-windef-rect

Exactly, 4 SDWORDs. It's a small glitch in Windows.inc that hasn't bothered anybody in the last 20 years because Assembly coders know their stuff :cool:
Title: Re: RECT Structure
Post by: hutch-- on August 06, 2020, 03:00:57 AM
I don't know where this folklore comes from but in assembler, the distinction does not exist, the same 32 bit value can be either signed or unsigned, try minus one (-1). The equates for either long OR SDWORD refer exclusively to the data SIZE, a DWORD 32 bit value.

Now yet again when a new member asks a question, the topic get flooded out with nonsense.
Title: Re: RECT Structure
Post by: jj2007 on August 06, 2020, 04:28:06 AM
I don't know where this folklore comes from but in assembler, the distinction does not exist

Code: [Select]
include \masm32\include\masm32rt.inc

.data
MyDwords dd -1, 0, 1
MySDwords SDWORD -1, 0, 1

.code
start:
  cls
  xor ebx, ebx
  print "DWORDS:", 13, 10
  .Repeat
.if MyDwords[4*ebx]<0
print str$(MyDwords[4*ebx]), " is below zero", 13, 10
.else
print str$(MyDwords[4*ebx]), " is zero or above", 13, 10
.endif
inc ebx
  .Until ebx>2
  xor ebx, ebx
  print "SDWORDS:", 13, 10
  .Repeat
.if MySDwords[4*ebx]<0
print str$(MySDwords[4*ebx]), " is below zero", 13, 10
.else
print str$(MySDwords[4*ebx]), " is zero or above", 13, 10
.endif
inc ebx
  .Until ebx>2
  inkey " "
  exit
end start

Output:
Code: [Select]
DWORDS:
-1 is zero or above
0 is zero or above
1 is zero or above
SDWORDS:
-1 is below zero
0 is zero or above
1 is zero or above
Title: Re: RECT Structure
Post by: hutch-- on August 06, 2020, 11:42:14 AM
 :thdn:

> Now yet again when a new member asks a question, the topic get flooded out with nonsense.

You are confusing a high level emulation with the function of assembler which in this case is 16 bytes of memory. As a structure its 16 bytes of STACK memory as a LOCAL or 16 bytes of either initialised or uninitialised memory. Likewise it can be 16 bytes of allocated memory. In MASM a 32 bit register is not sign specific and neither is an address in memory.

Try using the conditional jumps on the reverse data types. JG works fine on a bare DWORD just as JA works fine on an equated DWORD because the conditional testing is what decides whether the evaluation is either signed or unsigned.

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

    include \masm32\include64\masm64rt.inc

    .code

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

 entry_point proc

    USING r12,r13,r14,r15
    LOCAL pMem :QWORD

    SaveRegs

    mov pMem, alloc(64)             ; address in rax

    mov r12d, 1
    mov r13d, -2
    mov r14d, 3
    mov r15d, -4

    mov DWORD PTR [rax], r12d
    mov DWORD PTR [rax+4], r13d
    mov DWORD PTR [rax+8], r14d
    mov DWORD PTR [rax+12], r15d

    conout "Spot the difference",lf

    waitkey
    RestoreRegs
    .exit

 entry_point endp

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

    end

> Now yet again when a new member asks a question, the topic get flooded out with nonsense.