X86, разница между BYTE и BYTE PTR

В чем разница между этими двумя строками? Что здесь происходит в PTR?

;first
mov BYTE [ecx], 0  
;second
mov BYTE PTR [ecx], 0

Ответ 1

Сводка:

  • NASM/YASM требует word [ecx], когда размер операнда не подразумевается другим операндом. (В противном случае [ecx] в порядке).
  • Для MASM/TASM требуется 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.

Ответ 2

Вы используете разрешительный ассемблер, похоже, моя поддержка компилятора C для встроенной сборки наверняка недовольна этим. Правильный синтаксис - BYTE PTR, чтобы сообщить ассемблеру, что значение в регистре ECX должно обрабатываться как указатель. PTR. Но этот синтаксис, который указан выше, может уже сказать, что вы хотели использовать его в качестве указателя, поставив [скобки] вокруг имени регистра. Использование [ecx] уже дало понять, что вы хотели сохранить нуль в адрес, указанный в регистре ECX.

Итак, он знает, как использовать регистр ECX, единственное, что он не знает, - это то, сколько байтов должно быть установлено на ноль. Варианты 1, 2 или 4. Вы ясно дали понять, 1. BYTE.

Ответ 3

В 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