News:

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

Two questions on =

Started by Darmani, December 18, 2010, 01:51:38 AM

Previous topic - Next topic

Darmani

Hi! I have two questions on using the "=" directive (well, one question on using, and one question on misusing).

The first is on binding a name to a structure pointer. Consider the following ljine:

foo = dword PTR 0

It assembles perfectly, and I will thereafter be able to use "foo" instead of "0" in memory expressions.

However, suppose I wish to change the type:


STRUC STRUCT
field db ?
STRUC ENDS

foo = STRUC PTR 0


The last line there gives "error A2027: operand must be a memory expression." What am I doing wrong?


The second question is on storing a variable in a register. For example, suppose I am writing a method with the thiscall convention, and would like to keep the this pointer in edx for the duration of the call. To improve readability, I'd like to do something like this:


OPTION NOKEYWORD:<THIS>

this = edx
foo proc near
   mov this, ecx
   ...
foo endp



Of course, this returns a "constant expected" error, as "=" only binds to constants. What is the proper way to alias a name to a register?


I know there might be more idiomatic ways to do these things in MASM, but bear with me -- I (and the people I work with) learned assembly on NASM and GAS, and I'd prefer to keep this task relatively close to the basic assembly syntax.

dedndave

foo = dword PTR 0
is really a TEXTEQU, i think

STRUC is a reserved word - try using a different name to define the structure type
it is the old version of STRUCT (from masm 5 and earlier, i think) and is kept for compatibility

as for naming, i would use TEXTEQU
SomeTextName TEXTEQU <dword ptr [ebp-4]>
the assembler replaces all instances of "SomeTextName" with "dword ptr [ebp-4]"
it is all pre-processor stuff
TEXTEQU's, unlike EQU's, may be re-assigned


drizz

= means numeric
equ means "text" item {
There are details concerning equ:
with <> brackets equ is the same as textequ
without it it's symbolic equate
}

use: this equ edx

Also typcasting structure against 0 is not necessary in asm.
Stuff like FIELD_OFFSET RTL_FIELD_SIZE is generic in asm.

MYSTRUC.field ;; offset
sizeof MYSTRUC.field ;; field size
The truth cannot be learned ... it can only be recognized.

Darmani

Thanks for the tip on TEXTEQU!

You're going to have to rephrase the answer to the struct question though -- I don't understand.

dedndave

STRUC is a masm keyword
it is the same as STRUCT
so - you cannot use that to name your structure
just pick a different name
i think the same is true for field

something like this should work
MyStruc STRUCT
  afield db ?
MyStruc ENDS

japheth

Quote from: Darmani on December 18, 2010, 01:51:38 AM
Of course, this returns a "constant expected" error, as "=" only binds to constants. What is the proper way to alias a name to a register?

The '=' directive cannot be used to assign a literal to an identifier, you should use

    this EQU <edx>


jj2007

Tested with MASM 6.14, 6.15, 8.0, 9.0 and JWasm:

Quoteinclude \masm32\include\masm32rt.inc
.code
start:
   OPTION NOKEYWORD:<this>   ; it's a reserved word
;  this = eax                  ; fails
;  this textequ edx          ; fails
   this textequ <edx>      ; OK, and can be reassigned
   this equ <eax>      ; OK
   this equ (eax)        ; OK
   this equ [eax]        ; OK but means something else ;-)
   this equ [esi.WNDCLASSEX.cbSize]      ; OK
   this equ eax      ; OK, simplest variant
   mov this, edx
   print "OK"
   exit
end start

Darmani

Quote from: dedndave on December 18, 2010, 03:40:37 AM
STRUC is a masm keyword
it is the same as STRUCT
so - you cannot use that to name your structure
just pick a different name
i think the same is true for field

something like this should work
MyStruc STRUCT
  afield db ?
MyStruc ENDS


I apologize for being vague, but I had been referring to drizz's answer. I understand perfectly that STRUC is a reserved word. I had actually used a different name when testing, but made the mistake of changing the example name when I posted here. My question on what is wrong with "FOO PTR c" where FOO is a structure and c is a constant remains unanswered.

dedndave

"c" may be a reserved keyword, as well
i think it's used to refer to the c calling convention
pick happier names   :P

drizz

Quote from: Darmani on December 18, 2010, 10:44:22 AMMy question on what is wrong with "FOO PTR c" where FOO is a structure and c is a constant remains unanswered.
I'm not sure what you are trying to do with that. Maybe you want to use "assume" instead?

option nokeyword:<this>
  this equ ecx
mystruct struct
field db ?
mystruct ends
myproc proc c
  assume this:ptr mystruct
  mov al,[this.field]
  assume this:nothing
  ret
myproc endp


You could use constants as:
  foo equ <mystruct>
  mov al,[this+foo.field]

but i don't see the point





The truth cannot be learned ... it can only be recognized.

drizz

Quote from: Darmani on December 18, 2010, 03:20:52 AMYou're going to have to rephrase the answer to the struct question though -- I don't understand.
#define FIELD_OFFSET(Type,Field) ((ULONG_PTR)(&(((Type *)(0))->Field)))
In c/c++ the only way to get offset of a field within a structure is to typecast structure pointer to 0. I'm sorry if my assumption that you are a c/c++ programmer was wrong.
The truth cannot be learned ... it can only be recognized.

jj2007

The PTR is too much. This will work:
include \masm32\include\masm32rt.inc

MySTRUC STRUCT
field db ?
MySTRUC ENDS

foo textequ <MySTRUC> ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< OK

.code
ms MySTRUC <123>
start:
mov esi, offset ms
mov al, [esi.foo.field] ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< OK
OPTION NOKEYWORD:<this> ; it's a reserved word
; this = eax ; fails
; this textequ edx ; fails
this textequ <edx> ; OK, and can be reassigned
this equ <eax> ; OK
this equ (eax) ; OK
this equ [eax] ; OK but means something else ;-)
this equ [esi.WNDCLASSEX.cbSize] ; OK
this equ eax ; OK, simplest variant
mov this, edx
print "OK"
exit
end start

Darmani

Seems I broke the rule of always mentioning why I'm asking a question, and am suffering as a result. When will I learn.

My real question is: How do I refer to structs and struct pointers on the stack (without drawing too much on the idiosyncrasies of MASM)? For local ints, I do something like this:


myfunc proc near
  var1 = dword PTR -4
  var2 = dword PTR -8
  mov [ebp+var1], 1
  mov [ebp+var2], 2
myfunc endp



The obvious analogue for structs is to do something like this:


MySTRUC STRUCT
field db ?
MySTRUC ENDS

myfunc proc near
  foo = MySTRUC PTR -4
  lea eax, [ebp+foo]
  push eax
  call make_new_MyStruc
  mov eax, dword ptr [ebp+foo.field]


Of course, "foo = MySTRUC PTR -4" gives the assembly error that prompted me to create this thread.

I just tried a few variants of using assume and equ/textequ without success.

P.S.: Thanks drizz! I do sometimes program C, and I'll keep that trick in my head.

jj2007

Quote from: Darmani on December 18, 2010, 11:36:05 PM
How do I refer to structs and struct pointers on the stack?

WinMain proc hInst:HINSTANCE, hPrevInst:HINSTANCE, CmdLine:LPSTR, CmdShow:DWORD
LOCAL wc:WNDCLASSEX
mov wc.cbSize, SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, offset WndProc


Unless I have again completely misunderstood your question...

drizz

Quote from: Darmani on December 18, 2010, 11:36:05 PMSeems I broke the rule of always mentioning why I'm asking a question, and am suffering as a result.
Exactly!  :lol

Quote from: Darmani on December 18, 2010, 11:36:05 PMMy real question is: How do I refer to structs and struct pointers on the stack (without drawing too much on the idiosyncrasies of MASM)? For local ints, I do something like this:


myfunc proc near
  var1 = dword PTR -4
  var2 = dword PTR -8
  mov [ebp+var1], 1
  mov [ebp+var2], 2
myfunc endp



The obvious analogue for structs is to do something like this:


MySTRUC STRUCT
field db ?
MySTRUC ENDS

myfunc proc near
  foo = MySTRUC PTR -4
  lea eax, [ebp+foo]
  push eax
  call make_new_MyStruc
  mov eax, dword ptr [ebp+foo.field]


Of course, "foo = MySTRUC PTR -4" gives the assembly error that prompted me to create this thread.

foo equ <-4+MySTRUC>
so "mov eax, dword ptr [ebp+foo.field]" will evaluate to "mov eax, dword ptr [ebp+-4+MySTRUC.field]" but only if you don't use arithmetic on "foo" (2*foo would turn up wrong)

this will not work:
  lea eax, [ebp+foo]  ---->  lea eax, [ebp+-4+MySTRUC]
as standalone "MySTRUC" will evalueate to "sizeof MySTRUC"

I suggest instead of writing "ebp" every time make "foo" -> "ebp+offs" like:


myfunc proc near
  foo equ <[ebp-4]>
  lea eax, foo
  push eax
  call make_new_MyStruc
  mov eax, foo.MySTRUC.field


or


myfunc proc near
  foo equ <[ebp-4].MySTRUC>
  lea eax, foo
  push eax
  call make_new_MyStruc
  mov eax, foo.field


Also you can test how masm/jwasm responds  to multiple [] brackets


myfunc proc near
  foo equ <[[[ebp-4].MySTRUC]]>
  lea eax, foo
  push eax
  call make_new_MyStruc
  mov eax, [foo.field]

OR

myfunc proc near
  foo equ <[-4].MySTRUC>
  lea eax, [ebp+foo]
  push eax
  call make_new_MyStruc
  mov eax, dword ptr [ebp+foo.field]



A tip!
if you want to see what some line evaluates to, use:
%echo  mov eax, dword ptr [ebp+foo.field]

Also do not typecast "type ptr" where it's not necessary, it brings a bad name to masm/jwasm. ml/jwasm DOES CHECK TYPES unlike other assemblers.

HTH
The truth cannot be learned ... it can only be recognized.