理解 $ Location Counter 的行为 - var1 DWORD $ 汇编到 MASM 中数据节的开头,而不是行的开头

问题描述 投票:0回答:1

程序代码 - 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 在遇到

MOV AX, BX
后将位置计数器增加 2,因为该指令有两个字节长。

现在,看一下这个示例程序:

程序代码 - 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
的基地址。

为什么会有这种行为?

请随时纠正我。我不确定在这些测试用例之后如何准确地使用它。提供一些有关使用此

$
位置计数器的良好指导。

assembly x86 masm memory-address
1个回答
1
投票

进行此更改(DWORD -> EQU)可得到预期结果。

var2    EQU   $

ECX = 00DE4018

请注意

        MOV     ECX,var2

现在是立即(恒定)负载。

要“修复”MASM 的代码:

ofs2    EQU   $
var2    DWORD ofs2

或按照 Nate Eldredge 的建议:

var2    DWORD var2
© www.soinside.com 2019 - 2024. All rights reserved.