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

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

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

3 ответа

Резюме:

  • NASM / YASM требует word [ecx] когда размер операнда не подразумевается другим операндом. (Иначе [ecx] в порядке).
  • MASM / TASM требует word ptr [ecx] когда размер операнда не подразумевается другим операндом. (Иначе [ecx] в порядке).

Каждый из них душит синтаксис другого.


ВНИМАНИЕ: Это очень странная область без каких-либо стандартов ISO или легко доступных таблиц 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), и использование "byte ptr" более переносимо.

Также проверьте раздел 4.2.16 в книге из Индии и разделы 8.12.3 (и 8.11.3 "Типовые конфликты") в разделе "Программирование на языке ассемблера".

ОБНОВЛЕНИЕ: благодаря Фрэнку Котлеру кажется, что NASM "использует вариацию синтаксиса сборок Intel" (вики), которая не включает в себя операцию PTR.

ОБНОВЛЕНИЕ 1: имеется оригинальное "РУКОВОДСТВО ПО ЯЗЫКУ ASM86" от 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

Эта форма также может использоваться для переопределения атрибута типа переменной или метки. Например, если вы хотите получить доступ к уже определенной переменной слова в виде двух байтов, вы можете написать следующее:

MOV  CL, BYTE  PTR AWORD       ;get first byte
MOV  CL, BYTE  PTR AWORD + 1   ;get second byte

Значения поля:

тип Это поле может иметь одно из следующих значений: BYTE, WORD, DWORD, QWORD, TBYTE, NEAR, FAR

name Это поле может быть: 1. Имя переменной. 2. Название ярлыка. 3. Адрес или регистр выражения. 4. Целое число, представляющее смещение.

ОБНОВЛЕНИЕ 2: Благодаря Uni из Штутгарта! Существует оригинальное руководство 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 понимал, какой атрибут должен иметь выражение. Это особенно верно для атрибута типа. Всякий раз, когда вы размещаете прямые ссылки в вашей программе, 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. БАЙТ.

В MASM BYTE PTR [ecx] обращается к памяти по адресу ecx. BYTE [ecx] - синтаксическая ошибка ("синтаксическая ошибка встроенного ассемблера в" первом операнде "; найдено [[" ").

В NASM или YASM BYTE [ecx] обращается к памяти по адресу ecx. BYTE PTR [ecx] является синтаксической ошибкой ("ошибка: запятая, двоеточие или ожидаемый конец строки" в NASM, "неопределенный символ" 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
Другие вопросы по тегам