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