The MASM Forum

General => The Campus => Topic started by: kkurkiewicz on July 06, 2024, 03:55:21 AM

Title: When should arguments be declared as pointers?
Post by: kkurkiewicz on July 06, 2024, 03:55:21 AM
When defining parameters with the PROC directive, when exactly should they be marked as pointers?

For example, is it correct to define the prototype of the callback function used by SetWindowSubclass (https://learn.microsoft.com/en-us/windows/desktop/api/commctrl/nf-commctrl-setwindowsubclass) so that the type of the uIdSubclass and dwRefData parameters is just DWORD (as in the following code), or should it be PTR DWORD?

mysubclassproc PROC hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD, uIdSubclass:DWORD, dwRefData:DWORD

According to Windows Data Types (https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types), the type DWORD_PTR (the Windows type of dwRefData) is an unsigned long type for pointer precision to be used when casting a pointer to a long type to perform pointer arithmetic, and the same basically goes for UINT_PTR (the Windows type of uIdSubclass), so I think it should be DWORD but – as I understand it – the dwRefData value is supposed to act as a pointer to void, and I'd like it to be an offset. Do I understand that using PTR is just a matter of preference here, just like it's a matter of preference to enclose direct memory operands in brackets?
Title: Re: When should arguments be declared as pointers?
Post by: NoCforMe on July 06, 2024, 04:00:01 AM
In assembly language, there's no need to get that fancy with argument types.
A DWORD is a DWORD is a DWORD.
How it's used is entirely up to the code in the function. If it's a pointer, it gets dereferenced at some point. So far as the procedure definition (PROC) is concerned, it's just another 32-bit value that gets passed in on the stack. No need to communicate anything about its type or usage in the PROC parameters.
The important thing is the argument's size (and in 32-bit code that's always going to be a DWORD; no WORDs or BYTES allowed here).
This ain't C.
Title: Re: When should arguments be declared as pointers?
Post by: kkurkiewicz on July 06, 2024, 04:09:12 AM
So it is just a matter of personal preference, isn't it?
Title: Re: When should arguments be declared as pointers?
Post by: kkurkiewicz on July 06, 2024, 04:34:57 AM
I'd just like to know if it's worth the effort to use PTR knowing that the actual parameter is going to be an address and that it will be necessary for the function to dereference it.
Title: Re: When should arguments be declared as pointers?
Post by: NoCforMe on July 06, 2024, 04:56:50 AM
I would say no.
My preference is in how you name the parameter, which unfortunately a lot of programmers are pretty careless about, using cryptic, meaningless names.
You don't have to have a rigid system like Micro$oft uses ("Hungarian" notation). If it's a pointer, I would indicate that in the name:

DataObjectPtr

That way you, the programmer, know what it is every time you see that variable. And you'll know that you need to dereference it.
The function doesn't need to know anything.
Title: Re: When should arguments be declared as pointers?
Post by: jj2007 on July 06, 2024, 05:17:03 AM
Even in 64-bit code, it's irrelevant: you receive a QWORD even if you pass a DWORD because
  mov ecx, somevalue and
  mov rcx, somevalue

achieve the same result: rcx is set. What counts is what you pass, not how you name what you get.
Title: Re: When should arguments be declared as pointers?
Post by: NoCforMe on July 06, 2024, 05:30:03 AM
Quote from: jj2007 on July 06, 2024, 05:17:03 AMWhat counts is what you pass, not how you name what you get.
Au contraire, unless I misunderstand you.
The importance of naming is so that you, the programmer, know what the thing you're looking at is. No relevance to the assembler, yes.
Title: Re: When should arguments be declared as pointers?
Post by: jj2007 on July 06, 2024, 05:39:01 AM
Take SendMessage. Does anybody care for wParam or lParam? It's either DWORDs or pointers. Which are the same in 32-bit land.
Title: Re: When should arguments be declared as pointers?
Post by: NoCforMe on July 06, 2024, 05:55:16 AM
I'm not sure what your point is here, JJ. We were discussing how to identify whether a parameter is a pointer or not. True, the wParam and lParam parameters tell us nothing by their names; they can be used for all sorts of things, pointers, simple scalar values, indices, etc.

I'm talking about naming parameters to one of your functions to make it clear whether they're a pointer or not. Which is what the OP was asking about.
Title: Re: When should arguments be declared as pointers?
Post by: jj2007 on July 06, 2024, 08:19:46 AM
Quote from: NoCforMe on July 06, 2024, 05:55:16 AMI'm talking about naming parameters to one of your functions

Here is "my" function. Use comments.

SendMessage proc uses esi edi ebx uMsg:DWORD, arg1:WPARAM, arg2:LPARAM
  Switch uMsg
  Case WM_SETFONT
m2m CurrentFont, arg1  ; wParam is the handle
.if arg2
call RedrawThisControl  ; lParam is the redraw flag
.endif
  ...
Title: Re: When should arguments be declared as pointers?
Post by: kkurkiewicz on July 06, 2024, 08:27:53 AM
Quote from: NoCforMe on July 06, 2024, 05:55:16 AMI'm not sure what your point is here, JJ. We were discussing how to identify whether a parameter is a pointer or not. True, the wParam and lParam parameters tell us nothing by their names; they can be used for all sorts of things, pointers, simple scalar values, indices, etc.

I'm talking about naming parameters to one of your functions to make it clear whether they're a pointer or not. Which is what the OP was asking about.

Actually, I'm more interested in types rather than names. I know that ASM can be seen as (or is) typeless; I'd just like to know if there's any scenario where it's actually better to declare a parameter as a pointer.
Title: Re: When should arguments be declared as pointers?
Post by: NoCforMe on July 06, 2024, 08:35:53 AM
Quote from: kkurkiewicz on July 06, 2024, 08:27:53 AMI'd just like to know if there's any scenario where it's actually better to declare a parameter as a pointer.
No, because unlike C (and other languages), the assembler does nothing whatsoever to treat any variable automagically as a pointer: that's completely on you, the programmer.

Except for sizes (byte, word, dword, qword), assembly is completely typeless. There's not even any distinction, type-wise, between signed and unsigned variables; that's also up to you as the programmer to distinguish the two.

Really the only time you need to use PTR is when you're dealing with a memory reference that's otherwise invalid or ambiguous, similar to a C type cast:

    MOV    AX, WORD PTR wParam      ;Because wParam is a defined as a DWORD
   
Title: Re: When should arguments be declared as pointers?
Post by: jj2007 on July 06, 2024, 09:16:09 AM
Quote from: NoCforMe on July 06, 2024, 08:35:53 AMThere's not even any distinction, type-wise, between signed and unsigned variables

There is:

include \masm32\include\masm32rt.inc

.data
signedvar SDWORD -123
unsigned DWORD -123

.code
start:
  .if signedvar<0
print "sv is negative", 13, 10
  .else
print "sv is positive", 13, 10
  .endif
  .if unsigned<0
print "usv is negative", 13, 10
  .else
print "usv is positive", 13, 10
  .endif
  inkey "q.e.d."
  exit

end start
Title: Re: When should arguments be declared as pointers?
Post by: NoCforMe on July 06, 2024, 09:47:26 AM
Well, there is if you use macros, as you do. If you don't use them, no difference.

I manage to muddle along fine with JL/JG or JB/JA. You know, assembly language instructions.
Title: Re: When should arguments be declared as pointers?
Post by: NoCforMe on July 06, 2024, 10:00:32 AM
I hope I'm not belaboring my point too much, but I think it's worth defending as a Good Thing for programming, and as a (possible) answer to the OP's questions.

This simple matter of using a descriptive name to, essentially, give a variable a type is more profound than meets the eye. To answer JJ's suggestion of using comments to give a variable's type, I think my way is better, because it doesn't depend on a comment at the top of a function which may be half a mile away from where the variable gets used. (Well, sure, another comment there would do the trick, but what if you fail to put it in?)

Consider a function:
SomeFunction    PROC  numberPtr:DWORD
; numberPtr points to a # (DWORD)

When it comes time to use this parameter, because it's named as a pointer, we know we have to do this to get at the number it points to:
    MOV    EDX, numberPtr
    MOV    EAX, [EDX]

and not this:
    MOV    EAX, numberPtr

Assembler is (mostly) typeless; C is not. And while the C programmer might get annoyed at having to assign all those types to their variables, they benefit from it: the compiler helps to protect us from at least some dangers by warning us if, say, we try to use a pointer as a scalar or vice versa. (The C programmer can still get in plenty of trouble, as C is still a fairly low-level language.)

Assembly language gives us a lot more freedom, which of course means freedom to succeed or freedom to fail spectacularly. But as they say, with great freedom comes great responsibility, and it's the assembly-language programmer's responsibility to use their variables properly. Assembler lacks those guard rails that C provides. Which is why it's useful to come up with schemes to help avoid failures due to incorrect "types". Which is why I name my pointers "xxxxPtr".

Names matter. Pay attention to the names you assign your things, variables, functions, structures, structure elements. Come up with a scheme that works for you and stick to it.
Title: Re: When should arguments be declared as pointers?
Post by: jj2007 on July 06, 2024, 02:05:51 PM
Quote from: NoCforMe on July 06, 2024, 08:35:53 AMThere's not even any distinction, type-wise, between signed and unsigned variables

Quote from: NoCforMe on July 06, 2024, 09:47:26 AMWell, there is if you use macros

You know why there is the "M" in "MASM", right? Calling .if a "macro" is absurd. Be careful what you write in The Campus.
Title: Re: When should arguments be declared as pointers?
Post by: _japheth on July 06, 2024, 06:18:55 PM
Quote from: kkurkiewicz on July 06, 2024, 04:09:12 AMSo it is just a matter of personal preference, isn't it?

It depends. If you need to debug your code, using PTR combined with a type can greatly simplify the task. That's because the codeview debug information has all type information included that the debugger needs to know. So, for example, if the argument is a pointer to a STRUCT, the debugger will allow you'll to watch all members of that struct inside the PROC.
Title: Re: When should arguments be declared as pointers?
Post by: NoCforMe on July 06, 2024, 06:22:01 PM
Which debugger? Certainly not Olly, I don't think.
Title: Re: When should arguments be declared as pointers?
Post by: _japheth on July 06, 2024, 06:51:10 PM
Quote from: NoCforMe on July 06, 2024, 06:22:01 PMWhich debugger? Certainly not Olly, I don't think.

never used OllyDbg. But all debuggers based on the MS Debug Engine  (https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-engine-overview) should be ok. Even the ancient CodeView for DOS had that capability.
Title: Re: When should arguments be declared as pointers?
Post by: Greenhorn on July 06, 2024, 07:57:51 PM
Quote from: _japheth on July 06, 2024, 06:18:55 PM
Quote from: kkurkiewicz on July 06, 2024, 04:09:12 AMSo it is just a matter of personal preference, isn't it?

It depends. If you need to debug your code, using PTR combined with a type can greatly simplify the task. That's because the codeview debug information has all type information included that the debugger needs to know. So, for example, if the argument is a pointer to a STRUCT, the debugger will allow you'll to watch all members of that struct inside the PROC.


Quote from: _japheth on July 06, 2024, 06:51:10 PM
Quote from: NoCforMe on July 06, 2024, 06:22:01 PMWhich debugger? Certainly not Olly, I don't think.

never used OllyDbg. But all debuggers based on the MS Debug Engine  (https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-engine-overview) should be ok. Even the ancient CodeView for DOS had that capability.

I can confirm this.
With VS Debugger it's very useful and comfortable. WinDbg should also do the job.
Title: Re: When should arguments be declared as pointers?
Post by: daydreamer on July 06, 2024, 10:20:56 PM
I gonna try to random shuffle dword pointers for my card game than complete data for each card must become faster
Title: Re: When should arguments be declared as pointers?
Post by: jj2007 on July 07, 2024, 10:21:52 AM
include \masm32\include\masm32rt.inc
.code
MyTest proc arg1
Local rc:RECT
Local prc:PTR RECT
  mov rc.left, 111h
  mov rc.top, 222h
  mov rc.right, 333h
  mov rc.bottom, 444h
  lea eax, rc
  int 3
  mov prc, eax
  ret
MyTest endp
start:
  invoke MyTest, 55555555h
  exit
end start

(https://i.postimg.cc/JsHpPDTK/Decode-As-Structure.png) (https://postimg.cc/JsHpPDTK)
Title: Re: When should arguments be declared as pointers?
Post by: NoCforMe on July 07, 2024, 10:26:16 AM
Quote from: jj2007 on July 07, 2024, 10:21:52 AM(https://i.postimg.cc/JsHpPDTK/Decode-As-Structure.png) (https://postimg.cc/JsHpPDTK)
1. What debugger is that? Olly?

2. You don't need to declare anything as a PTR to do that, correct? Just right-click and choose "Decode as structure" anywhere in the data, yes?

Nice to be able to do that, for sure.
Title: Re: When should arguments be declared as pointers?
Post by: zedd on July 07, 2024, 10:30:20 AM
Quote from: NoCforMe on July 07, 2024, 10:26:16 AM
Quote from: jj2007 on July 07, 2024, 10:21:52 AM(https://i.postimg.cc/JsHpPDTK/Decode-As-Structure.png) (https://postimg.cc/JsHpPDTK)
1. What debugger is that? Olly?
Looks like olly...  :biggrin: but I have never seen that option. Using a plugin??
Title: Re: When should arguments be declared as pointers?
Post by: jj2007 on July 07, 2024, 05:27:25 PM
Quote from: zedd151 on July 07, 2024, 10:30:20 AMLooks like olly...  :biggrin: but I have never seen that option. Using a plugin??

That's Olly indeed, and not a plugin.

The choice of structures is limited. I've checked the whole Olly folder to find out where this info is stored, no luck.
Title: Re: When should arguments be declared as pointers?
Post by: TimoVJL on July 07, 2024, 08:00:39 PM
poide + poasm
;include \masm32\include\masm32rt.inc

RECT STRUC
left sdword ?
top sdword ?
right sdword ?
bottom sdword ?
RECT ENDS

.code
MyTest proc arg1
Local rc:RECT
Local prc:PTR RECT
  mov rc.left, 111h
  mov rc.top, 222h
  mov rc.right, 333h
  mov rc.bottom, 444h
  lea eax, rc
  int 3
  mov prc, eax
  ret
MyTest endp
start:
  invoke MyTest, 55555555h
  ret
end start
(https://i.postimg.cc/4KBb17G6/poide-dbg.png) (https://postimg.cc/4KBb17G6)
Title: Re: When should arguments be declared as pointers?
Post by: kkurkiewicz on July 09, 2024, 02:17:08 AM
I think I understand, thank you.
I just got confused by the _PTR suffix in the name of the type.
Title: Re: When should arguments be declared as pointers?
Post by: Greenhorn on July 09, 2024, 07:22:11 AM
Quote from: kkurkiewicz on July 09, 2024, 02:17:08 AMI think I understand, thank you.
I just got confused by the _PTR suffix in the name of the type.


The _PTR sais that this type always has the size of a Pointer, which means in x86 4 bytes and in x64 8 bytes.

ifdef _WIN64
INT_PTR            typedef sqword
UINT_PTR        typedef qword
LONG_PTR        typedef sqword
ULONG_PTR        typedef qword
else
INT_PTR            typedef sdword
UINT_PTR        typedef dword
LONG_PTR        typedef sdword
ULONG_PTR        typedef dword
endif