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!
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).
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:
cmp somerect.left, 0
jl itsnegative
However, to be fair, this works only with SDWORDs:
.if somerect.left<0
... do something for the negative case ...
.endif
With the existing Windows.inc version, you can use this workaround:
.if sdword ptr somerect.left<0
... do something for the negative case ...
.endif
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.
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
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.
Hi ToutEnMasm,
Hutch is right, here is how the structure is defined in windows.inc :
RECT STRUCT
left dd ?
top dd ?
right dd ?
bottom dd ?
RECT ENDS
The size of RECT is 16 bytes.
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.
Hi ToutEnMasm,
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 ) :
#include <windows.h>
#include <stdio.h>
int main(void)
{
printf("sizeof(RECT)=%u\n",sizeof(RECT));
return 0;
}
sizeof(RECT)=16
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.
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
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.
Quote from: Vortex on August 05, 2020, 11:24:31 PM
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:
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.
Quote from: 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
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:
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
: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.