程序代码 - 1
.386
.model flat
.data
Array1 DWORD 1,2,3,4,5
var1 DWORD $
.code
start PROC
MOV EAX, OFFSET Array1
MOV EBX, var1
LEAVE
RET
start ENDP
END
程序代码 - 1 个输出
EAX = 001E4000
EBX = 001E4000
为什么
var1
是.data段的基地址的答案已经在这里得到了解答。
为什么会有这种行为?
当遇到 .code、.data、.bss、.const 等段时,位置计数器将设置为零偏移量。
仅当汇编器遇到任何发出目标代码的指令或伪操作码时,位置计数器的偏移值才会增加。
例如,MASM 会为写入目标代码文件的每个字节递增位置计数器。 MASM 在遇到
后将位置计数器增加 2,因为该指令有两个字节长。MOV AX, BX
现在,看一下这个示例程序:
程序代码 - 2
.386
.model flat
.data
Array1 DWORD 1,2,3,4,5
var1 DWORD ($ - Array1)
.code
start PROC
MOV EAX, OFFSET Array1
MOV EBX, var1
LEAVE
RET
start ENDP
END
程序代码 - 2 个输出
EAX = 000B4000
EBX = 00000014
在程序代码 - 2 中,我注意到输出发生了变化。我认为这是因为位置计数器的地址计算所致。我也用一些测试用例对其进行了测试,并且产生了相同的结果。
在程序代码 - 2 中,var1 的位置计数器的值发生了变化,可能是因为我执行了地址计算
($ - Array1)
。这可能是观察到的行为的一个原因,但我不完全确定。
根据作者在上一个问题中的回答,位置指针
$
仅在汇编器遇到某些发出目标代码的指令时才会递增。
现在的问题是:程序代码 - 2 中发生了什么?它看起来像一个变量声明,所以位置计数器不应该增加。但当看到结果时,却发现并非如此。它似乎生成了目标代码,尽管我不完全确定。
现在,请参阅程序代码 - 3:
程序代码 - 3
.386
.model flat
.data
Array1 DWORD 1,2,3,4,5
var1 DWORD ($ - Array1)
var2 DWORD $
.code
start PROC
MOV EAX, OFFSET Array1
MOV EBX, var1
MOV ECX, var2
LEAVE
RET
start ENDP
END
程序代码 - 3 个输出
EAX = 00DE4000
EBX = 00000014
ECX = 00DE4000
在程序代码 - 2 中,var1 似乎有一个指向
Array1
末尾的偏移量。正如我提到的,我不知道这种行为背后的确切原因。
然而,程序代码 - 3 使得预测发生的事情变得更加困难。对于
var1
,位置计数器递增,然后似乎递减或设置回 Array1
的基地址。
为什么会有这种行为?
请随时纠正我。我不确定在这些测试用例之后如何准确地使用它。提供一些有关使用此
$
位置计数器的良好指导。
进行此更改(DWORD -> EQU)可得到预期结果。
var2 EQU $
ECX = 00DE4018
请注意
MOV ECX,var2
现在是立即(恒定)负载。
要“修复”MASM 的代码:
ofs2 EQU $
var2 DWORD ofs2
或按照 Nate Eldredge 的建议:
var2 DWORD var2