Вот несколько разных способов реализации Перечисления типов .
Самый простой способ - просто перебрать объект, добавив инвертированные пары ключ-значение к объекту. Единственным недостатком является то, что вы должны вручную установить значение для каждого члена.
function _enum(list) {
for (var key in list) {
list[list[key] = list[key]] = key;
}
return Object.freeze(list);
}
var Color = _enum({
Red: 0,
Green: 5,
Blue: 2
});
// Color → {0: "Red", 2: "Blue", 5: "Green", "Red": 0, "Green": 5, "Blue": 2}
// Color.Red → 0
// Color.Green → 5
// Color.Blue → 2
// Color[5] → Green
// Color.Blue > Color.Green → false
И вот lodash mixin , чтобы создать перечисление с использованием строки. Хотя эта версия немного больше задействована, она автоматически выполняет нумерацию. Все методы lodash, используемые в этом примере, имеют обычный эквивалент JavaScript, поэтому вы можете легко их отключить, если хотите.
function enum() {
var key, val = -1, list = {};
_.reduce(_.toArray(arguments), function(result, kvp) {
kvp = kvp.split("=");
key = _.trim(kvp[0]);
val = _.parseInt(kvp[1]) || ++val;
result[result[val] = key] = val;
return result;
}, list);
return Object.freeze(list);
}
// Add enum to lodash
_.mixin({ "enum": enum });
var Color = _.enum(
"Red",
"Green",
"Blue = 5",
"Yellow",
"Purple = 20",
"Gray"
);
// Color.Red → 0
// Color.Green → 1
// Color.Blue → 5
// Color.Yellow → 6
// Color.Purple → 20
// Color.Gray → 21
// Color[5] → Blue
Вы используете разрешительный ассемблер, похоже, моя поддержка компилятора 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, «неопределенный символ« 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
Резюме:
word [ecx]
, когда размер операнда не подразумевается другим операндом. (В противном случае [ecx]
в порядке). word ptr [ecx]
, когда размер операнда не подразумевается другим операндом. (В противном случае [ecx]
в порядке). Каждый из них задыхается от синтаксиса другого.
ВНИМАНИЕ: Это очень странная область без каких-либо стандартов ISO или легкодоступные таблицы BNF; и я не специалист по прохождению через минные поля проприетарного синтаксиса MASM.
В вашем случае нет разницы, но оператор PTR может означать в других случаях:
http://www.c-jump.com/CIS77/ASM/Instructions/I77_0250_ptr_pointer.htm
В общем случае оператор оператора PTR принудительно обрабатывает выражение как указатель указанного типа:
blockquote>.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» (wiki), который не включает операцию PTR.
UPDATE1: имеется оригинальная «РУКОВОДСТВО ПО ЭКСПЛУАТАЦИИ ЯЗЫКА ASM86» от Intel, 1981-1983, оператор PTR определен на pa ge 4-15:
Оператор PTR
Синтаксис: введите имя PTR
Описание: Оператор PTR используется для определения ссылки на память с помощью определенный тип. Ассемблер определяет правильную инструкцию для сборки на основе типа операндов в инструкции. Существуют определенные случаи, когда вы можете указать операнд, который не имеет типа. Эти случаи связаны с использованием числовых или регистровых выражений. Здесь оператор PTR используется для указания типа операнда. Следующие примеры иллюстрируют это использование:
blockquote>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 переменной или метки. Если, например, вы хотели получить доступ к уже определенной переменной слова как два байта, вы могли бы закодировать следующее:
blockquote>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. Целое число, которое представляет смещение.
blockquote>UPDATE2: Благодаря Uni из бета-накопителя Stuttgart! Существует оригинальное руководство MACRO-86 от Microsoft (1981). Страница 3-7:
Оператор PTR можно использовать другим способом, чтобы сохранить байт при использовании прямых ссылок. Если вы определили FOO как постоянную константу, вы можете ввести оператор:
blockquote>MOV [BX],FOO
Возможно, вы захотите сослаться на FOO как на немедленный байт. В этом случае вы можете ввести любой из операторов (они эквивалентны):
blockquote>MOV BYTE PTR [BX],FOO MOV [BX],BYTE PTR FOO
Эти утверждения указывают MACRO-86, что FOO является байтом немедленным. Создается меньшая команда.
blockquote>И страница 3-16:
Операторы переопределения
Эти операторы используются для переопределения сегмента , смещение, тип или расстояние между переменными и метками.
Указатель (PTR)
blockquote><attribute> PTR <expression>
Оператор PTR переопределяет тип (BYTE, WORD , DWORD) или расстояние (NEAR, FAR) операнда.
<attribute>
- новый атрибут; новый тип или новое расстояние.
<expression>
- это операнд, атрибут которого должен быть переопределен.Самое важное и частое использование для PTR заключается в том, чтобы убедиться, что MACRO-86 понимает какой атрибут должен иметь выражение. Это особенно верно для атрибута type. Всякий раз, когда вы размещаете ссылки в своей программе, PTR очищает расстояние или тип выражения. Таким образом, вы можете избежать фазовых ошибок.
Второе использование PTR заключается в доступе к данным по типу, отличному от типа определения переменной. Чаще всего это происходит в структурах. Если структура определена как WORD, но вы хотите получить доступ к элементу в виде байта, PTR является оператором для этого. Однако гораздо более простой способ - ввести второй оператор, который также определяет структуру в байтах. Это устраняет необходимость использования PTR для каждой ссылки на структуру. См. Директиву LABEL в разделе 4.2.1 «Директивы памяти».
Примеры:
blockquote>CALL WORD PTR [BX][SI] MOV BYTE PTR ARRAY, (something) ADD BYTE PTR FOO,9
После прочтения этого и поиска некоторых определений синтаксиса из этих документов я думаю, что запись PTR является обязательной. Использование
mov BYTE [ecx], 0
неверно в соответствии с руководством MACRO-86.