Сбивающие с толку скобки в MASM32

Я пытаюсь справиться с MASM32 и путаюсь в следующем:

Я думал, что скобки были использованы для косвенности, поэтому, если у меня есть предопределенная переменная

 .data
   item dd 42

то

 mov ebx, item

помещает содержимое "item", то есть число 42, в ebx и

 mov ebx, [item]

будет помещать адрес "item", то есть где 42 хранится, в ebx.

Но следующий код в консольном приложении:

 mov ebx, item
 invoke dwtoa, ebx, ADDR valuestr 
 invoke StdOut, ADDR valuestr
 mov ebx, [item]
 invoke dwtoa, ebx, ADDR valuestr 
 invoke StdOut, ADDR valuestr

печатает 42 раза дважды. Чтобы получить адрес "элемента", мне, кажется, нужно

 mov ebx, [OFFSET item]
 invoke dwtoa, ebx, ADDR valuestr 
 invoke StdOut, ADDR valuestr

Кто-нибудь может объяснить, для каких квадратных скобок в MASM, или указать мне хорошую ссылку.

Ответ 1

MASM необычен для языка ассемблера, который имеет типы. MASM знает, как вы определили символ item, который является ячейкой памяти типа DWORD. Когда вы используете его как операнд, вы знаете, что вы (вероятно) означаете, что хотите сохранить значение по адресу, а не значение адреса. Так что неважно, используете ли вы item или [item] MASM предполагает, что вы имеете в виду позднее. Если вам действительно нужен адрес элемента, вам нужно использовать OFFSET item.

С другой стороны, если вы определили item как константу, используя item = 42, тогда mov ebx, item будет загружать ближайшее значение. Из-за этой двусмысленности вам нужно знать, как был определен item, чтобы определить, является ли он непосредственным операндом или операндом памяти, поэтому рекомендуется избегать использования голого символа в качестве операнда.

Я должен добавить, что квадратные скобки [] почти ничего не означают для MASM, когда вы просто используете символы. Они только что-то значат, когда вы используете их с регистрами. Вот несколько примеров:

item    DD  42
const   =   43

    mov eax, item             ; memory operand (the value stored at item)
    mov eax, [item]           ; memory operand
    mov eax, OFFSET item      ; immediate operand (the address of item)
    mov eax, [OFFSET item]    ; immediate operand

    mov eax, const            ; immediate operand (43)
    mov eax, [const]          ; immediate operand
    mov eax, ds:[const]       ; memory operand (the value at address 43)
    mov eax, OFFSET const     ; immediate operand
    mov eax, [OFFSET const]   ; immediate operand

    mov eax, 42               ; immediate operand
    mov eax, ebx              ; register operand (the value of EBX)
    mov eax, [ebx]            ; indirect operand (the value pointed to by EBX)

Так что без регистров квадратные скобки показывают только ваши намерения. Вы должны поместить квадратные скобки вокруг символов, если вы собираетесь использовать их в качестве операндов памяти, и используйте OFFSET с символами, которые вы собираетесь использовать в качестве мгновенных значений.