В чем разница между этими двумя строками? Что здесь происходит в PTR?
;first
mov BYTE [ecx], 0
;second
mov BYTE PTR [ecx], 0
В чем разница между этими двумя строками? Что здесь происходит в PTR?
;first
mov BYTE [ecx], 0
;second
mov BYTE PTR [ecx], 0
Сводка:
word [ecx]
, когда размер операнда не подразумевается другим операндом. (В противном случае [ecx]
в порядке).word ptr [ecx]
, когда размер операнда не подразумевается другим операндом. (В противном случае [ecx]
в порядке).Каждый из них задыхается от другого синтаксиса.
ПРЕДУПРЕЖДЕНИЕ: Это очень странная область без каких-либо стандартов ИСО или легкодоступных таблиц BNF; и я не специалист по прохождению через минные поля проприетарного синтаксиса MASM.
В вашем случае это может быть не разница, но оператор PTR может означать в других случаях:
http://www.c-jump.com/CIS77/ASM/Instructions/I77_0250_ptr_pointer.htm
В общем случае выражение оператора PTR принудительно обрабатывается как указатель указанного типа:
.DATA
num DWORD 0
.CODE
mov ax, WORD PTR [num] ; Load a word-size value from a DWORD
Я думаю, что существуют также специфические требования для ассемблера (nasm/tasm/other asm), а использование "байтового ptr" более переносимо.
Также проверьте раздел 4.2.16 в книга из Индии и разделы 8.12.3 (и 8.11.3 "Типы конфликтов" ) в "Программе программирования языка программирования".
ОБНОВЛЕНИЕ: спасибо Фрэнку Котлеру, похоже, что NASM "использует вариант синтаксиса сборки Intel" (wiki), который не включает операцию PTR.
UPDATE1: существует оригинальная "ASM86 LANGUAGE REFERENCE MANUAL" от Intel, 1981-1983, оператор PTR определен на стр. 4-15
Оператор PTR
Синтаксис: введите имя PTR
Описание: Оператор PTR используется для определения ссылки на память определенного типа. Ассемблер определяет правильную инструкцию для сборки на основе типа операндов в инструкции. Существуют определенные случаи, когда вы можете указать операнд, который не имеет типа. Эти случаи связаны с использованием числовых или регистровых выражений. Здесь оператор PTR используется для указания типа операнда. Следующие примеры иллюстрируют это использование:
MOV WORD PTR [BX], 5 ;set word pointed to by BX = 5
INC DS:BYTE PTR 10 ;increment byte at offset 10
;from DS
Эта форма также может использоваться для переопределения атрибута type переменной или метки. Если, например, вы хотели получить доступ к уже определенной переменной слова как два байта, вы можете закодировать следующее:
MOV CL, BYTE PTR AWORD ;get first byte
MOV CL, BYTE PTR AWORD + 1 ;get second byte
Значения полей:
type Это поле может иметь одно из следующих значений: BYTE, WORD, DWORD, QWORD, TBYTE, NEAR, FAR
name Это поле может быть: 1. Имя переменной. 2. Имя метки. 3. Адрес или регистр. 4. Целое число, которое представляет смещение.
UPDATE2: Благодаря Uni из Stuttgart битрейдер! Существует оригинальное руководство MACRO-86 от Microsoft (1981). Страница 3-7:
Оператор PTR может использоваться другим способом для сохранения байта при использовании прямых ссылок. Если вы определили FOO в качестве постоянной константы, вы можете ввести оператор:
MOV [BX],FOO
Вы можете обратиться к FOO как к байту немедленно. В этом случае вы можете ввести любой из операторов (они эквивалентны):
MOV BYTE PTR [BX],FOO
MOV [BX],BYTE PTR FOO
Эти утверждения указывают MACRO-86, что FOO является байтом немедленно. Создается меньшая команда.
И страница 3-16:
Операторы переопределения
Эти операторы используются для переопределения сегмента, смещения, типа или расстояния между переменными и метками.
Указатель (PTR)
<attribute> PTR <expression>
Оператор PTR переопределяет тип (BYTE, WORD, DWORD) или расстояние (NEAR, FAR) операнда.
<attribute>
- новый атрибут; новый тип или новое расстояние.
<expression>
- это операнд, атрибут которого должен быть переопределен.Самое важное и частое использование для PTR заключается в том, чтобы убедиться, что MACRO-86 понимает, какой атрибут должен иметь выражение. Это особенно верно для атрибута type. Всякий раз, когда вы размещаете ссылки в своей программе, PTR очищает расстояние или тип выражения. Таким образом, вы можете избежать фазовых ошибок.
Второе использование PTR заключается в доступе к данным по типу, отличному от типа в определении переменной. Чаще всего это происходит в структурах. Если структура определена как WORD, но вы хотите получить доступ к элементу в виде байта, PTR является оператором для этого. Однако гораздо более простой способ - ввести второй оператор, который также определяет структуру в байтах. Это устраняет необходимость использования PTR для каждой ссылки на структуру. См. Директиву LABEL в разделе 4.2.1 "Директивы памяти".
Примеры:
CALL WORD PTR [BX][SI]
MOV BYTE PTR ARRAY, (something)
ADD BYTE PTR FOO,9
После прочтения этого и поиска некоторых определений синтаксиса из этих документов я считаю, что запись PTR является обязательной. Использование mov BYTE [ecx], 0
неверно в соответствии с руководством MACRO-86.
Вы используете разрешительный ассемблер, похоже, моя поддержка компилятора C для встроенной сборки наверняка недовольна этим. Правильный синтаксис - BYTE PTR, чтобы сообщить ассемблеру, что значение в регистре ECX должно обрабатываться как указатель. PTR. Но этот синтаксис, который указан выше, может уже сказать, что вы хотели использовать его в качестве указателя, поставив [скобки] вокруг имени регистра. Использование [ecx] уже дало понять, что вы хотели сохранить нуль в адрес, указанный в регистре ECX.
Итак, он знает, как использовать регистр ECX, единственное, что он не знает, - это то, сколько байтов должно быть установлено на ноль. Варианты 1, 2 или 4. Вы ясно дали понять, 1. BYTE.
В MASM BYTE PTR [ecx] обращается к памяти по адресу ecx. BYTE [ecx] - синтаксическая ошибка ( "синтаксическая ошибка встроенного ассемблера в" первом операнде "; найдена" ['").
В NASM или YASM BYTE [ecx] обращается к памяти по адресу ecx. BYTE PTR [ecx] - синтаксическая ошибка ( "ошибка: запятая, двоеточие или конец ожидаемой строки" в NASM, "undefined символ` PTR" в YASM).
В TASM, BYTE PTR [ecx] и BYTE [ecx] эквивалентны - как память доступа по адресу ecx.
Однако в ассемблерном Gnu-газе при использовании синтаксиса intel BYTE PTR [ecx] обращается к памяти в ecx, но BYTE [ecx] фактически обращается к памяти по адресу ecx + 1. То есть, BYTE [ecx] эквивалентен BYTE PTR [ecx + 1], который не кажется ни строгим, ни документированным.
Ассемблер Gnu версии 2.18, 2.24 или 2.26.1:
cat > foo.S << EOF
.intel_syntax noprefix
movb BYTE [ecx], 0
movb BYTE PTR [ecx], 0
.att_syntax prefix
EOF
as foo.S
objdump -dM intel a.out
0: 67 c6 41 01 00 mov BYTE PTR [ecx+0x1],0x0
5: 67 c6 01 00 mov BYTE PTR [ecx],0x0