MASM:在.data声明中使用当前位置计数器($) [英] MASM: Using Current Location Counter ($) in .data declaration
问题描述
我遇到了有关MASM中当前位置计数器的问题.
I met a problem about the Current Location Counter in MASM.
这是我的汇编代码,我使用Visual Studio 2013 Express进行组装
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
我认为ptr1,ptr2和ptr5应该具有自己的位置值.
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具有相同的地址,并且它们之间没有偏移.
ptr1, ptr2, ptr5 have the same address and there is no offset between them.
使用$进行声明时会出现什么问题?
What's problem when using $ for declaration ?
推荐答案
您的问题似乎是MASM中的错误(或者正如Microsoft可能会说的那样,这是功能").问题不在于DWORD指令未生成目标代码或它们未提前汇编程序的位置计数器.如果前者为true,则它们根本不会出现在可执行文件中;如果后者为true,则它们都将具有相同的地址.
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.
问题在于,当在数据定义中使用MASM时,在某些情况下会错误地将当前段的起始偏移(在生成的目标文件中)用作$
的值,而不是使用当前位置计数器.以下代码基于您的示例进行了演示(并显示了一个简单的解决方案):
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
这是IDA拆卸MASM为上述汇编代码创建的目标文件的方式:
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
您会注意到,mov eax, $
指令表明DWORD指令已正确地推进了位置计数器.您还将注意到,ptr1
,ptr2
和ptr5
均已在该段的开头使用$$000000
进行了初始化,完全忽略了先前的MOV指令和DWORD指令均已高级化的事实位置计数器.
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.
另一方面,MASM确实正确评估了$ - ptr1
.这将计算ptr1
与当前位置计数器之间的距离,即前四个DWORD指令的总长度(以字节为单位)为16.这意味着至少在这种情况下,MASM使用正确的$
值.
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 $
.
最后,该示例说明了如何解决此问题.只需使用命名标签代替$
,就像在ptr6 DWORD ptr6
行中一样.这将导致汇编器正确生成一个指针,该指针被初始化为指向自身.
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.
这篇关于MASM:在.data声明中使用当前位置计数器($)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!