MASM: Using Current Location Counter ($) in .data declaration
assembly, masm, x86
Solution
Your problem seems to be a bug in MASM (or as Microsoft would likely put it, a "feature"). The problem isn't that the DWORD directives aren't generating object code or that they aren't advancing the assembler's location counter. If the former was true then they wouldn't show up in the executable at all, and if the later was true they would all have the same address.
The problem is that MASM incorrectly uses the offset of the start of the current segment (in the generated object file) for the value of `$` instead of the current location counter in certain contexts when used in a data definition. The following code, based on your example, demonstrates this (and shows a simple solution):
.386
PUBLIC ptr1, ptr2, ptr5, ptr6, len
_DATA SEGMENT
mov eax, $
mov eax, $
ptr1 DWORD $
ptr2 DWORD $
ptr5 DWORD OFFSET $
ptr6 DWORD ptr6
len DWORD $ - ptr1
mov eax, $
_DATA ENDS
END
Here's how IDA disassembles the object file created by MASM for the above assembly code:
.data:00000000 $$000000:
.data:00000000 mov eax, offset $$000000
.data:00000005 $$000005:
.data:00000005 mov eax, offset $$000005
.data:0000000A ptr1 dd offset $$000000
.data:0000000E ptr2 dd offset $$000000
.data:00000012 ptr5 dd offset $$000000
.data:00000016 ptr6 dd offset ptr6
.data:0000001A len dd 16
.data:0000001E $$00001E:
.data:0000001E mov eax, offset $$00001E
You'll notice that the `mov eax, $` instructions show that location counter is being correctly advanced by the DWORD directives. You'll also notice that `ptr1`, `ptr2` and `ptr5` all have been initialized with `$$000000` which is at the start of the segment, completely ignoring the fact that both the previous MOV instructions and the DWORD directives have advanced the location counter.
On the other hand, MASM does evaluate `$ - ptr1` correctly. This calculates the distance between `ptr1` and the current location counter, which is 16, the total length in bytes of the previous four DWORD directives. This means in at least in this context MASM uses the correct value of `$`.
Finally the example shows how work around this problem. Just use a named label instead of `$`, like in the line `ptr6 DWORD ptr6`. This results in the assembler correctly generating a pointer that is initialized to point at itself.
Problem
I met a problem about the Current Location Counter in MASM. Here is my assembly code, and I used Visual Studio 2013 Express for assembling ``` .386 .model flat,stdcall .stack 8192 ExitProcess proto,dwExitCode:dword .data ptr1 DWORD $ ptr2 DWORD $ ptr5 DWORD $ .code main proc mov eax, $ mov eax, $ invoke ExitProcess,0 main endp end main ``` In my opinion, I think that ptr1, ptr2, and ptr5 should have their own location value. But it's not correct in fact. When in debugging mode, the variables show the same result. ptr1, ptr2, ptr5 have the same address and there is no offset between them. What's problem when using $ for declaration ?