.data
ptr_to_str dd offset string
string db "qwerty", 0

assembles to:


.data:00402000 dd [COLOR=blue]offset string[/COLOR]
.data:00402004 string db 'qwerty', 0

no problems here.

BUT:


.data
ptr_to_str dd 0 ; place for pointer
string db "qwerty", 0

off = ($ - ptr_to_str)
ORG ($ - off) ; location pointer to ptr_to_str
dd offset string ; try define string address
ORG ($ + off - 4) ; location pointer to previous state

assembles to:


.data:00402000 dd [COLOR=red]0[/COLOR]
.data:00402004 string db 'qwerty', 0

I know that current location pointer is used in offset calculation.
Since pointer is changed, offset fails. Clear.
But i need some way to do this:
I have some fixed address that i know (ptr_to_str).
Somewhere in listing i use macro that defines some string (var/structure).
At this point i want return current location pointer to known address (ptr_to_str) and write there offset of new defined string (var/structure). Than restore current location pointer and assembling goes farther.

Don't ask me why i need to do such thing. It's difficult to explain.
Simply assume i need to make it work whis way.
Please any suggestions.
Posted on 2002-07-11 06:17:38 by Four-F
Try:



_foo dd offset @foo
@foo:
string db "qwerty", 0


Now you are telling it to use the address of @foo a label, not a data type.

or try:


_foo dd offset @foo
@foo label dword
string db "qwerty", 0
Posted on 2002-07-11 08:35:30 by ThoughtCriminal
No, no, no. It's completely not what i want. Sorry.
I try to explain it better.

My example above is over-simplify.
I define my own data segment.
The first X dwords are placement for pointers to structures.
These structures will be defined later by expanding some macro.


MyOwnSegment SEGMENT
MyMacro MACRO
structure STRUCTURE <,,,>
ENDM
; here i need to place offset to defined structure
; in place of pointer01
MyOwnSegment ENDS

The macro can be placed anywhere and arbitrary number of times.
Between structures can be other definitions.
As i don't know how many times my macro will be placed in code,
it's impossible use label stuff.
The X is known, say 32, and i could define 32 pointers:


MyOwnSegment SEGMENT
pointer01 dd offset structure01
pointer02 dd offset structure02
...
pointer32 dd offset structure32
MyOwnSegment ENDS

But macro that defines structures can be used, say, only 4 times.
I don't know how many.
So, first 4 offsets will be valid, but there is no structure05, structure06...

Hope my problem is more clear now.
Posted on 2002-07-11 09:29:14 by Four-F
How about including some info in the macro as to which segment it should place the structure definition e.g.


MyMacro MACRO
MyOwnSegment
structure STRUCTURE <,,,>
.code
ENDM

MyOwnSegment SEGMENT
; here i need to place offset to defined structure
; in place of pointer01
MyOwnSegment ENDS


I'm not sure if it'll work but it seems reasonable to me. you may want to add an argument to the macro for the structure name?
Posted on 2002-07-11 09:45:40 by MArtial_Code
Four-F, I too have struggled with such "org" redefines some time ago. I cannot remember all pitfalls but I know I have given up at last and found a solution less elegant but working. IMO this stuff is partly compiler dependant and you shouldnt rely on masm behave totally identical in different versions.

But for your example I suggest trying:



.data
ptr_to_str: ;or ptr_to_str label dword instead
org $ + 4
string db "qwerty", 0

off = ($ - ptr_to_str)
ORG ($ - off) ; location pointer to ptr_to_str
dd offset string ; try define string address
ORG ($ + off - 4) ; location pointer to previous state


Just avoid duplicate definitions for the same address. Its a guess, I havent tried it out.

japheth
Posted on 2002-07-11 10:32:10 by japheth


.data
ptr_to_str:
org $ + 4
[COLOR=crimson]; <- here goes arbitrary number of data.[/COLOR]
[COLOR=crimson]; so, (org $ + 4) doesn't work[/COLOR]
string db "qwerty", 0


Thanks all!

Have found some solution. I like it not much, but hope it will work.
I can't define virtual offset but i can define offset from begining of the segment.

Something like this:


MyOwnSegment SEGMENT
MyMacro MACRO
structure STRUCTURE <,,,>
ENDM

NUM_STRUCTURES_DEFINED = NUM_STRUCTURES_DEFINED + 1

; displace location pointer to begining of pointers array
off = ($ - (pointer01 + 4*(NUM_STRUCTURES_DEFINED-1)))
ORG $ - off
; write RVA of structure to appropriate pointer
dd off-sizeof STRUCTURE
; restore location pointer
ORG ($ + off - 4)

MyOwnSegment ENDS


dd off-sizeof STRUCTURE defines RVA (relative virtual address)
from beginning of MyOwnSegment.
Since VA (virtual address) of MyOwnSegment will be known at run time,
and array of pointers is always at the beginning of MyOwnSegment,
i can simply calculate VA to defined structure.
Hope this solves my main problem.
But since project is in its very first stage, things may change.
So, if you have other solution, please, throw it here. Thanx.
Posted on 2002-07-11 11:34:36 by Four-F
Four-F, I have done the same thing by using two segments:
MyStructure MACRO vars:VARARG

LOCAL _struct

SpecialOne$A SEGMENT
dd OFFSET _struct
SpecialOne$A ENDS


SpecialOne$B SEGMENT
_struct MyStruct <vars&>
SpecialOne$B ENDS
ENDM
The linker will combine the segments by the same name and order them by part after $. I think this is what you are after? I despise the use of ORG - it will give you nothing but problems, IMO. This is because MASM wasn't designed to use it this way.

Here is an example:
MyStructure MACRO vars:VARARG

LOCAL _struct

SpecialOne$A SEGMENT
dd OFFSET _struct
SpecialOne$A ENDS


SpecialOne$B SEGMENT
_struct db vars&
SpecialOne$B ENDS
ENDM


MyStructure "Hello",0,"World",0,0
MyStructure "ASM",0,"is",0,"the",0,"BEST!!",0,0
This will create two pointers in the $A segment and add the two strings to the $B segment. In the object file they will appear in one segment with $A first, followed by $B. Elegant solution, imo. :)

I use the same method to order the CONST data in my proggies - there are string, fpu, and mmx coonstants and they are grouped together and placed in one segment. Also, I don't use the simple segment definitions: .code, .data, .data? They don't play well with jumping in and out of multiple segments - you don't have to keep saving what segment the parser was in - it's saved automatically by MASM.

Something I starting doing recently, is creating a segment partition for COM object pointers - to ensure that I release everything before the program exits. I've been using this with DX8. Maybe this is redundant. I'll see how it works in time.
Posted on 2002-07-11 12:07:53 by bitRAKE
Thank you, bitRAKE!
Seems to be nice solution.
I'll play with it.
Posted on 2002-07-12 04:42:02 by Four-F
Yeah! Works exactly i wanted, and simplifies many other things.
I looked up all my masm docs and found nothing about this trick.
Undoc trick? bitRAKE, how did you know about it?
Posted on 2002-07-12 07:53:34 by Four-F
four-f, the "segment$order" is linker-, not masm-specific. It's documented
somewhere in MSDN.
Posted on 2002-07-13 06:50:30 by f0dder
There is a couple of sentences somewhere like f0dder said, but I really learned by looking at some asm output from VC++. You know that damn M$ doesn't want to confuse the C++ progragrammers by explaining too much about what is really going on. I'm glad to have helped.

Maybe you can see some other neat tricks that can be done with this? Note that the segment names can be constructed by a macro. So, we now have the ability to place code/data in the executable in a different location after it has been assembled. For example, say we place some code in segment Special$mmm then we decide we need some code before this piece of code. We create segment Special$fmm and place the code in it. Then we need some code between these two segments. We create segment Special$hmm and place some code in it.

Granted this is rather extreme. :grin:
Posted on 2002-07-13 09:57:07 by bitRAKE
bitrake, I found out about the stuff while trying to create "manual" import libraries with nasm... I couldn't get the the dependency stuff 100% working, though :/

You know, if I only use one function from a DLL I don't want to import everything from that DLL. Also if I use no functions from a DLL, I don't want to include the "mainthunk" (DLL-name, causing the DLL to be imported) either... but of course the "mainthunk" must be included if I include any function from a DLL... and must of course only be included once. Argh :)

Unfortunately I couldn't make the pieces all fit, and had other things to spend my time on, so my "manual import libraries for namesum-rather-than-plainascii import of functions" :P was never completed.

It would probably be better to have the tool generating a ar-lib of ms-coff files (ie, standard win32 library format) instead of relying on nasm for backend anyway... just can't be bothered to pick up the project again right now :)
Posted on 2002-07-14 11:24:49 by f0dder
f0dder, hopefully, better tools come along that
make that kind of think a piece of cake. ;)
Posted on 2002-07-14 12:09:47 by bitRAKE
hopefully... but it's still a dependency hell ;)
Posted on 2002-07-14 12:13:18 by f0dder
We are all dependent on many things. I stand my ground and ensure my dependencies remain around. For it always is co-dependency.
Posted on 2002-07-14 13:41:48 by bitRAKE
real-life yes... don't ever depend on people who don't depend on you. You'll learn that rather quickly, although learning who depends on you is a longer process..
Posted on 2002-07-14 15:27:29 by f0dder