Error a2045 missing angle bracket or brace in literal

Error a2045 missing angle bracket or brace in literal This forum has migrated to Microsoft Q&A. Visit Microsoft Q&A to post new questions. Answered by: Question After installed SP1 in VS2008 Linker -> Additional Dependencies -> msvcrt.lib Custom Build Step -> General -> Command Line -> ml -c -Zi «-Fl$(IntDir)$(InputName).lst» «-Fo$(IntDir)$(InputName).obj» «$(InputPath)» Custom Build […]

Содержание

  1. Error a2045 missing angle bracket or brace in literal
  2. Answered by:
  3. Question
  4. Answers
  5. Руководство по проектированию макросов в MASM32
  6. I. От автора
  7. I.1 Для тех, кто впервые.
  8. I.2. Примечания (обо всём понемногу)
  9. I.3. Особенности терминологии
  10. I.4. Благодарности
  11. II. Лень – двигатель Макро
  12. III. Макромир MASM
  13. III.1. Функционирование макросов
  14. III.2. Определение макро переменных и строк
  15. III.3. Обработка выражения в MASM
  16. III.4. Целочисленные выражения MASM
  17. III.5. Вычисление рекурсивных выражений
  18. III.6. Встроенные макрофункции и директивы
  19. III.7. Символ макроподстановки
  20. III.8. Макроблоки
  21. III.9. Отладка макроопределений и заключение
  22. III.10. Абстрактный алгоритм анализа строки MASM (Дополнение)

Error a2045 missing angle bracket or brace in literal

This forum has migrated to Microsoft Q&A. Visit Microsoft Q&A to post new questions.

Answered by:

Question

After installed SP1 in VS2008

Linker -> Additional Dependencies -> msvcrt.lib

Custom Build Step -> General -> Command Line ->
ml -c -Zi «-Fl$(IntDir)$(InputName).lst» «-Fo$(IntDir)$(InputName).obj» «$(InputPath)»

Custom Build Step -> General -> Outputs -> $(IntDir)$(InputName).obj

Answers

It looks like the ml tries to compile the .vcproj file 🙂 Nothing good can come out of this, obviously.

Review and fix your project settings, especially what is $(InputPath).

As far as I know, PRJ0019 may occur when a tool returned an error code but no error message. This can happen, for example, if you redirect the output of MIDL to NUL. This error can also occur when you are running as a member of the Users group and Administrative access is needed.

If your custom build steps or events are not behaving as you expect, there are several things you can do to try to understand what is going wrong.
1->Make sure that the files your custom build steps generate match the files you declare as outputs.
2->If your custom build steps generate any files that are inputs or dependencies of other build steps (custom or otherwise), make sure that those files are added to your project. And make sure that the tools that consume those files execute after the custom build step.
3->To display what your custom build step is actually doing, add @echo on as the first command. The build events and build steps are put in a temporary .bat file and run when the project is built. Therefore, you can add error checking to your build event or build step commands.
4->Examine the build log in the intermediate files directory to see what actually executed. The path and name of the build log is represented by the MSBuild macro expression, $(IntDir)$(MSBuildProjectName).log.
5->Modify your project settings to collect more than the default amount of information in the build log. On the Tools menu, click Options . In the Options dialog box, click the Projects and Solutions node and then click the Build and Run node. Then, in the MSBuild project build log file verbosity box, click Detailed .
6->Verify the values of any file name or directory macros you are using. You can echo macros individually, or you can add copy %0 command.bat to the start of your custom build step, which will copy your custom build step’s commands to command.bat with all macros expanded.
7->Run custom build steps and build events individually to check their behavior.

Best regards,
Helen Zhao

Helen Zhao [MSFT]
MSDN Community Support | Feedback to us

Источник

Руководство по проектированию макросов в MASM32

Пойми в Хаосе Разное, и стань человеком.
Осознай Единое в Различном – и будь Богом.

I. От автора
I.1. Для тех, кто впервые
I.2. Примечания (обо всём понемногу)
I.3. Особенности терминологии
I.4. Благодарности
II. Лень – двигатель Макро
III. Макромир MASM
III.1. Функционирование макросов
III.2. Определение макро переменных и строк
III.3. Обработка выражения в MASM
III.4. Целочисленные выражения MASM
III.5. Вычисление рекурсивных выражений
III.6. Встроенные макрофункции и директивы
III.7. Символ макроподстановки
III.8. Макроблоки
III.9. Отладка макроопределений и заключение
III.10. Абстрактный алгоритм анализа строки MASM (Дополнение)

I. От автора

В этом руководстве раскрывается тема создания, использования (а главное – проектирования) макросов и макрофункций в проектах на MASM32.

Что не так важно в ЯВУ, то очень важно в программировании на ассемблере. Если выстроить по приоритетам недостатки программирования на ассемблере, то первым недостатком будет не объём строк написанного кода (как нестранно), а отсутствие средств, обеспечивающих хороший стиль написания кода.

Что значит стиль? А что значит плохой или хороший? Это можно быстро понять на простом примере.

Допустим, у вас есть процедура объёмом на несколько экранов. Вы её написали месяц назад, а теперь вам нужно несколько изменить её поведение. Для того, чтобы сделать это, вам необходимо:

  1. Вспомнить её алгоритм (если забыли)
  2. Вспомнить особенности реализации (у вас должны быть комментарии)
  3. Вспомнить какой участок кода, чем занимается.

Если код процедуры был прооптимизирован, вероятней всего вам захочется, чтобы после модификации он остался настолько же оптимальным, а поэтому вы должны вспомнить все тонкости кода, или только того участка, который подлежит модификации.

А это не так то просто, даже если исходник написан вами, в вашем неповторимом стиле.

Если этот стиль будет хорошим, вы потратите меньшее время, если бы стиль был бы плохим.

Хороший стиль программирования – это сэкономленное время, которое можно потратить на понимание, модификацию или, как это называют, сопровождение кода.
Стиль программирования – это архитектура исходного кода – не только его внешнее оформление, но и использование констант, разбиения кода на функции или процедуры, способы вызова функций и процедур, согласованность структур, их потенциал к расширению, гибкость алгоритмов и многое другое. Стиль программирования сложно отделить от архитектуры самой программы, так как хорошо спроектированная программа не может иметь плохого стиля программирования.

Конечно же, на ЯВУ легче писать качественно оформленные программы, хотя бы, потому что ЯВУ уже имеет готовые средства выражения, и шаблоны мышления.

Что такое шаблоны мышления? Всё чем вы так активно пользуетесь:
— типы
— функции
— классы
— массивы
— указатели на типы
— пространства имён
— шаблоны (С++)
Всё это направляет ваше понимание программирования как пространства сотканного из таких абстракций.

Недавно я прочёл следующую мысль на форуме WASM.RU:

Да, зачем вы пишите программы на asm под Win32, лучше уже писать под DOS, там хоть нет этого бесконечно однообразного кода создания окон и обработки сообщений.

Такое заявление говорит, что программист не желает писать проекты более чем на 6 000 строк (или 3 000 ). Вместо того чтобы извлечь великую выгоду из единообразия кода, мы ругаем его. А ведь это первый звонок к автоматизации программирования.

Неужели программирование asm может быть похоже на Delphi (ох как его не любят некоторые)? Снова интегрированная среда? Конечно. (Жаль, её всё-таки нет!) Но это не значит, что она играет отрицательную роль. Хотя о средствах автоматизации и их создании мы поговорим в другой работе.

Ассемблер не определяет шаблонов мышления, и практически не имеет средств выражения каких либо шаблонов (из-за чего автор пользуется им).

Очень сложно назвать директиву proc средством выражение процедурной модели программирования.

Однако я могу ручаться, если вы научитесь писать качественно стилизированные программы на ассемблере, то на ЯВУ… .

Об искусстве стилизации или проектировании архитектуры написано слишком мало, а рассказать хотелось бы слишком много. Только нельзя объять необъятное, и потому цель этого руководства рассказать об использовании макросов в MASM32, а также о том, как их можно либо нужно использовать, чтобы более качественно стилизировать код.

I.1 Для тех, кто впервые.

Если вы ещё не работали с макросами, или работали, но очень мало, я спешу признаться, что это руководство не предназначалось для начинающих. Но благодаря рекомендациям и советам TheSvin/HI-TECH я решился добавить в него вырезки и упражнения, которые позволят вам быстро войти во вкус макромира MASM32. Если же вы уже имеете дело с макросами, тогда это руководство укрепит ваши знания и представления по данной теме.

Для исследования макромира MASM мы воспользуемся директивой echo, которая позволит вывести нам на экран то, что творится в препроцессоре MASM. Очень удобно, а главное наглядно. Я уверен, что вы быстро усвоите этот материал.

I.2. Примечания (обо всём понемногу)

В данной работе я часто пишу: «Препроцессор ML». Кто-то из умников (или просто жаждущих подловить «на горячем») воскликнет: «Да какой же такой ML.EXE – препроцессор? Наглая ложь». На всякий случай оговорю, что здесь имеется ввиду не утверждение «ML – препроцессор», а именование его подсистемы – препроцессор.

Всё, что есть в этом руководстве не взято с потолка, и не является вымышленным. Весь код проверен, и работает именно так как описано, если только автор случайно не ошибся, что так же случается.

Многое из того, что написано в этом руководстве недокументированно (или плохо документировано) в официальном. Поэтому вы всегда должны помнить, что если в следующих версиях ML (например, 8.0) что-то не будет работать, никто не виноват.

Если вы думаете, что я дизассемблировал ML.EXE – то ошибаетесь. Алгоритмы работы, приведённые здесь, получены логическим путём на основе знаний работы компиляторов, а поэтому их не следует воспринимать как истинные. Важна сама логика работы, понимание которой, поможет вам безболезненно использовать макро, допуская меньшее количество ошибок.

На самом деле MASM очень плохо документирован, и видно MS совсем не относится к нему как к продукту (что вполне очевидно). Хотя уже в MSDN 2002 был внесён раздел MASM Reference, и всё равно – вы не найдёте лучше описания чем в MASM32 by Hutch.

Когда вы прочтете, то воскликните: «Да, зачем мне такой ML?». Есть NASM и FASM – главная надежда мира ассемблерщиков. Однако и теперь ML всё ещё выигрывает у них по удобству эксплуатации, большей частью видимо благодаря Хатчу, и многим замечательным людям, поддерживающим MASM32. Кто знает, может после этой статьи кто-то воскликнет: «Я знаю, какой должен быть компилятор мечты асмовцев!». И напишет новый компилятор. (Автор шутит ?)

Уверен, что программисты из MS вряд ли прочтут эту статью (они плохо знакомы с русским), и оно к лучшему. Возможно, такая статья могла бы их огорчить, а я не люблю портить настроение людям, трудами которых пользуюсь. (Снова шутит, только про что?)

И наконец-то мне в свою очередь хочется порадоваться, что многие вопросы по макросам в MASM закрыты на долгое время, во всяком случае, для русскоязычной аудитории. (Шутит, или нет? Гм…)

I.3. Особенности терминологии

Терминология этой статьи различается от терминологии принятой в MASM.

В частности автором было предложено называть:

Можно было бы попросту выбрать терминологию MASM, однако последняя не позволяет объяснять материал систематически. То есть все четыре вида выражений – по сути, являются переменными или константами. Однако в терминологии MASM два последних определения называются текстовыми макро, подчёркивая их связь с макросами.

Если пойти этим путём, то тогда и первые два определения – являются упрощёнными определениями макро. Если разработчики желали подчеркнуть, что сама суть внутренней реализации ML представляет текстовые макросы как макро, то тогда не ясны те все эффекты функциональности, обсуждаемые в этой статье.

Что имеет ввиду автор?
Посмотрите что такое макроопределение – это некий текст, который как бы «вставляется» препроцессором в исходный текст программы в месте вызова макро.
А что такое в терминологии MASM numeric equates, или text macro – это некоторые переменные, значения которых «подставляются» в исходный текст программы во время компиляции вместо имён этих переменных.
Таким образом, можно сказать, что определения представленные выше – макро, но в упрощённом их виде.

Этот спор не решаем, что не так и важно. Поэтому автор отдаёт предпочтение двум терминам для «text macro»: «текстовой макро» и «строковая макропеременная».

Понятие: «numeric equates» является общим для первых двух случаев, и разрывает смысловую связь с двумя последними определениями. Поэтому я пользуюсь своим вариантом терминологии, который подчёркивает, что определения:

являются подобными макро. А, кроме того, первое из низ – константа, а второе – переменная.

I.4. Благодарности

Не могу не написать этот пункт, ибо не только автору обязана эта статья.

Она обязана замечательной версии Win98 с инсталляцией от 2000, которая отформатировала весь мой винчестер, и унесла в небытие первый вариант настоящей статьи.

Не малая заслуга в вопросе терминологии MASM, и его разрешении принадлежит Four-F, который как он сам мне признался, съел на макросах собаку, при чём без соли .

Когда я думаю, чтобы было бы без самого Маниакального редактора в Inet, CyberManiacа, то понимаю: без его правок мои статьи приводили бы в ужас, и лишали разума всех морально неустойчивых читателей. CyberManiac: «Только такой замечательный безумец как ты может выдержать ЭТО. » .

FatMoon, Rustam, The Svin – вы дали понять мне то, что такая статья действительно нужна, и это, наверное, самое главное. Вряд ли я бы так долго работал над ней, если бы меня никто не подталкивал.

Всех кого я забыл поблагодарить здесь, и кого не забыл, жду в условном месте в условное время для раздачи благодарностей.

С уважением, Edmond/HI-TECH

II. Лень – двигатель Макро

Когда говорят, что лень – это двигатель прогресса, видимо лицемерят или преувеличивают. Скорее это нежелание выполнять одну и ту же работу очень часто. Первая парадигма к созданию макро звучит так:

Если есть что-то похожее, что нужно делать очень часто, я могу оформить это как макроопределение.

Ассемблер, дающий программисту полную свободу в использовании методик программирования, совершенно лишает его средств для выражения этих методик. Например, ООП. В MASM32 нет классов, конструкторов и других механизмов, поддерживающих эту абстракцию. Зато вместо ООП Вы можете придумать множество других методик и абстракций (как, например модель серверов).

Та или иная методика программирования обязательно состоит из каких-либо компонентов, которые являются подобными друг другу. Например, следующие макро очень любимы в примерах пакета MASM32:

Предположим, что кому-то так надоело писать:

И он решил придумать макро для этого. Эта пара команд осуществляет пересылку данных из одной ячейки памяти в другую. То есть теперь в программе, когда вы захотите написать push/pop, вы можете заменить это некой m2m операнд1, операнд2. Посмотрите на эти два участка кода:

Первый вариант не только занимает меньше строк (что тоже важно), но и намного понятнее, чем push/pop (если вы, знаете что такое m2m). Конечно, если говорить о макро m2m, то он имеет и очень важный недостаток.

Мощь макро была бы сказочной, если бы MASM умел следить за кодом, или ему можно было бы указать, что, например, сейчас регистр ebx == 0, или eax никем не используется. Хотя мы попробуем достичь подобного эффекта самостоятельно.

Этот недостаток потеря контроля над оптимальностью кода. Например, более быстрыми, по сравнению с парой команд push/pop, являются mov eax,… Употребляя макро m2m, вы получаете худший код, если стремитесь оптимизировать по скорости. И здесь есть две стороны проектирования кода:

  1. Эффективность кода
  2. Совершенство стилистики

Используя макро m2m, вы повышаете уровень стилистики, так как сокращаете время на понимание исходного кода (вами же или другим программистом). Однако с другой стороны вы теряете эффективность.

Это одна из вечных задач архитектора – найти баланс между эффективностью в коде и совершенством стилистики.

Другая парадигма использования макро звучит так:

Если, объединяя что-то в одно целое, я улучшаю стиль кода – это можно сделать в виде макроопределения.

Эта парадигма отличается от предыдущей тем, что создание макроопределения обуславливается только улучшением стилизации кода, и не имеет особой практической ценности. Например, я объявил такие макро для определения кода начала и конца в главном модуле программы:

В этих макро нет по сути никакой пользы, кроме эстетической. Зато, глядя на код, можно сразу понять, что это не что иное, как начало программы нечто вроде main() в C++.

И последняя парадигма использования макро:

Если ты используешь технологию программирования – попытайся заключить её в комплекс макроопределений.

Например, для модульного программирования нужно создать макросы для определения модуля, его частей, кода и данных.

Наиболее важная часть использования макро. Посмотрите, например, файл Objects.INC из пакета MASM32 в папке oop (NaN & Thomas).
Мы начнём создание первых макро со следующей задачи.

Наверное, вы знаете, что EXE приложения всегда могут загружаться по адресу равному:

Во-первых, это даёт нам право убрать из приложения всю Relock секцию, тем самым, уменьшив объём образа (если эта секция нужна для систем плагинов, её можно держать отдельно).

Во-вторых мы можем более не вызывать функцию GetModuleHandle, что так же полезно для нас. Использование константы PROGRAM_IMAGE_BASE очень удобно. Однако, что будет значить это удобство, если всё-таки PROGRAM_IMAGE_BASE не определено? Это будет означать, что мы обязаны переписать весь код. А если этого кода много?

Определённо об этом нужно позаботится заранее. Давайте же будем решать эту проблему при помощи макро! Для этого нам станут необходимыми некоторые знания о том, как обрабатывается макро, и что это такое.

III. Макромир MASM

Макрос представляет собой именованный участок исходного текста программы, который обрабатывается компилятором каждый раз в том месте, где вызывается макрос.

Пример:
Создайте небольшой модуль с именем macro.asm.
И напишите в нём несколько строчек

Так действует директива echo. С помощью неё можно подсмотреть значения переменных.

Если вы не знаете, как это работает, не волнуйтесь, обо всём будет рассказано. А пока несколько экспериментов:

Взгляните на код программы под отладчиком. Что у вас получилось? Что будет, если вы измените текст внутри макроопределения?

Каким будет вывод на экран во время компиляции?

С этого момента вам придётся различать в ассемблере ML две подсистемы: препроцессор и компилятор. Если компилятор переводит код мнемоник в машинный код, вычисляет значения меток и смещений, то препроцессор занимается вычислением выражений этапа компиляции, и что самое важное – процессом раскрытия макросов.

Подобно многим объектам мира программирования макро имеет два состояния в исходном тексте: определение, и использование.

Таким образом, мы будем иметь дело с определением макроса (макроопределением), и его вызовом (использованием макроса).
Макроопределением называется любой текст, заключённый между ключевыми словами:

При каждом вызове макро, а именно:

Будет анализироваться и исполнятся текст, заключённый в макро. Именно так это и реализовано в ML. Поскольку текст в макроопределении не компилируется, то естественно, вы не увидите сообщений об ошибке, даже если с точки зрения ассемблера эта ошибка будет в теле макроопределения. Однако ошибка появится при попытке вызова макроопределения, её могут выдать вам, либо сам препроцессор, либо компилятор, если текст, сгенерированный препроцессором является неверным с точки зрения компилятора.

Каждый раз, когда препроцессор встречает макроопределение, он помещает его имя в специальную таблицу, и копирует его тело к себе в память (это не обязательно именно так, но вам должна быть понятна суть). Встретив макроопределение, препроцессор не проверяет, а есть ли макро с таким же именем. Это значит, что макро можно переопределять.

Вы можете самостоятельно удалять макроопределения, из памяти препроцессора используя директиву PURGE:

Эта директива удаляет тело макроопределения, однако не удаляет имя макро из таблицы имён. Таким образом, в данном случае:

Разработчики ML задумывали эту директиву для разрешения конфликтов между файлами с множеством макросов, однако мне совершенно не ясно как ей можно воспользоваться. Если вы хотите получить эффект «удаления» макро, лучше применять следующий метод:

В этом случае при попытке воспользоваться таким макро, компилятор выдаст ошибку, и вы будете проинформированы о его вызове, что намного лучше неведения. Поэтому просто запомните: «Не нужно использовать директиву PURGE».

Конечно же, использование макро не было бы столь полезным, если бы макро не имел формальных параметров. При вызове макро, препроцессор заменяет все имена формальных параметров их непосредственными значениями в теле макроопределения. Список формальных параметров разделяется запятой, и может иметь вид:

Здесь:
Param0 – пример определения параметра.
Param1:REQ – ключевое слово REQ указывает на то, что этот параметр обязательный. То есть, если он не будет указан, вы получите ошибку этапа компиляции.
Param2:= – пример параметра, который имеет значение по умолчанию. То есть если этот параметр не будет указан при вызове макро, он будет равен этому значению.

Заметьте, что при вызове макро параметр может быть не определён:

Значение второго параметра неопределенно.

Param3:vararg – становится именем параметра, который воспринимает всё остальное как строку. При этом запятые между параметрами так же попадают в строку, а значит число параметров макроса в принципе неограниченно.

Ограничениям являются особенности архитектуры компилятора. Так, например, компилятор имеет ограничение на длину логической строки, которая равна 512 байтам.

Конечно же, после параметра с директивой vararg не возможно объявить другие параметры.

Обратите внимание, что если при определении формального параметра в макро нет директивы – он считается необязательным параметром. Более подробно о вызове макро и значении параметров я расскажу далее.

Пример:
Так что же происходит с формальными параметрами?
Посмотрите, как работает препроцессор ML:

1. Препроцессор берёт текст внутри макро, и заменяет в нём все
слова param1, param2, на их значения:
«
mov eax, var
mov ebx, 123
»

2. Полученный текст вставляет на место вызова макро, и передаёт компилятору.

Вот интересно, а что будет если:

Можно различать два вида макро – макропроцедуры и макрофункции.

В официальном руководстве MASM различается четыре основных вида макро.
Text macros – текстовый макрос
Macro procedures – макро-процедура
Repeat blocks – блок повторения
Macro functions – макро-функция
Однако автор считает, что разделение макро на два вида – лучше систематизирует материал, и отражает суть темы.

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

Заметьте, что к макрофункции невозможно обратится как к макро, вы всегда должны заключать формальные параметры макрофункции между «()», иначе MASM не будет распознавать её как макрофункцию:

Препроцессор MASM анализирует текст макроопределения на наличие директивы exitm, и помечает макрос как макрофункцию.

Ключевое слово exitm , аналогично оператору return в C++, выполнение макро заканчивается, и возвращается необязательный параметр retval. Этот параметр – строка, которую должен вернуть макрос.

Если в макро директива EXITM употребляется без параметров:
EXITM
То препроцессор считает, что это макропроцедура, а не макрофункция.
Если в макроопределении есть два вида EXITM с параметром и без, то ML выдаст ошибку о недопустимом использовании директивы EXITM.
EXITM <>
EXITM
: error A2126: EXITM used inconsistently
Это подчёркивает тот факт, что макрофункцией считается только макро, который возвращает значение (хотя бы пустое), а директива EXITM без параметров не возвращает никакого значения, что недопустимо в макрофункции.

Таким образом, окончательно будем считать, что макро, которые не возвращают значение – это макропроцедуры, а макро, которые возвращают значение (хотя бы пустую строку) – это макрофункции.

Что касается директивы endm, которая заканчивает каждое макроопределение, в руководстве написано, что при помощи неё так же можно указать возвращаемый параметр:
endm
Однако на практике это не так. ? Очень странно, хотя об этом чётко написано в руководстве.

Заметьте, что макропроцедура может быть вызвана только в начале строки:

Макрофункция может быть вызвана в любых выражениях:

III.1. Функционирование макросов

Чтобы строить макросы, важно понимать, как они работают, и как их обрабатывает MASM. Давайте рассмотрим типичный макро, и этапы его обработки.

1. Компилятор встречает лексему MyMacro

2. Он проверяет, содержится ли эта лексема в словаре ключевых слов

3. Если нет, то он проверяет, содержится ли эта лексема в списке макросов.

4. Если да, он передаёт текст, содержащийся в макро препроцессору. Препроцессор заменяет все вхождения формальных параметров в этом тексте на их значения. В данном случае мы имеем:

5. Препроцессор возвращает компилятору обработанный текст, который после компилируется.

Обратите внимание на пункт 4 и 5. Они ключевые. Очень часто при работе с макроопределениями появляются ошибки из-за неверного понимания порядка генерирования макро текста. Например:

А теперь самостоятельно опишите порядок действий компилятора при вызове этого макро. Запишите его себе куда-нибудь, так чтобы сравнить, и смотрите на вывод:

Прежде чем объяснять действительный порядок, я оговорюсь, что директива echoникогда не обрабатывает определённые константы, такие как PROGRAM_IMAGE_BASE.

Это утверждение справедливо даже тогда, когда перед директивой echo стоит оператор %, который может раскрывать только текстовые макроопределения. То есть выражение:

Теперь, когда мы немного порассуждали можно привести тот текст, который генерируется из макро:

Это означает следующее:

  1. При вызове макро, значение формальных параметров воспринимается как текст, и передаётся в макро как строка.
  2. Исключение составляют лишь макрофункции, результат выполнения которых вычисляется и присваивается значению параметра.

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

То получим вывод:

Давайте рассмотрим ещё один пример, который хорошо показывает, как работает макро. Например, вы определили макропроцедуру (именно его, а не макрофункцию). То когда вы пишите такое:

Что делает препроцессор ML:

1. Считывает всю строку до символа возврата каретки;

2. Смотрит, как вы определили параметры в макро;

3. Сканирует строку на наличие символа «,» или « »;

Вам может показаться странным, но препроцессору всё равно, какие символы идут во время вызова макро. То есть вы можете вызвать макро так:

Посмотрите как СИльно (от буквы ) будет выглядеть макро в MASM:

4. Назначает формальным параметрам (любого типа, кроме VARARG) макро участки строк, которые были определены разделителями запятыми (предварительно очистив от хвостовых и начальных пробелов, если только строка не была определена в угловых кавычках <>);

5. Если макро содержит формальный параметр типа VARARG, то ML сперва инициализирует значениями (согласно пункту 4) обычные формальные параметры, и только потом назначает параметру типа VARARG (который может быть только один в конце списка параметров) всю строку до конца.

Если вы пишите макровызов как
@Macro Param1 , Param2
То значение параметров будут:
param1 = «Param1»
param2 = «Param2»
Если вы хотите передать сами значения строк, то должны заключит их в угловые кавычки:
@Macro ,

6. Препроцессор разрешает все вызовы макрофункций, если они есть в лексемах параметра, и присваивает их результат соответствующему параметру. Если лексему в строке параметра предваряет символ %, то он вычисляет её значение до того, как передаст строку внутрь макро.

Благодаря именно такому порядку:
1. Разделение строки на макропараметры
2. Поиск и Вызов макрофункций в значениях макропараметров
3. Присвоение результатов соответствующему макропараметру

в следующем случае:

строка, возращаемая макрофункцией присваивается параметру param1, а не param2, param3

Теперь вы в состоянии объяснить следующую ситуацию:

Как нужно было бы изменить этот макро (именно макро, а не макрофункцию), чтобы предупреждение не выдавалось? А почему оно происходит?

Если вы с лёгкостью ответили на этот вопрос, значит, материал усвоен, иначе советую ещё раз прочитать его, и ответить на следующий вопрос.

Как должен понять компилятор следующий код:

Естественно отвечать на этот вопрос вы должны без помощи компилятора (то есть проверить компиляцией). Если вы не можете ответить на этот вопрос, или неуверенны в верности ответа, я поменяю задание:

Запустите его в ML. Если и теперь вы сомневаетесь – перечитайте этот пункт снова и снова, продолжая экспериментировать.

III.2. Определение макро переменных и строк

Я бы назвал следующее:

макропеременными (с тем фактом, что переменная может иметь константный тип).

В терминологии MASM:

Потому что под термином «переменная» понимается:

Переменные являются частью программы, а макропеременные живут только на этапе компиляции. По сути, они есть более простым видом макроопределений, и поэтому их стоит понимать как специальные макро, которые так же раскрываются препроцессором.

Макропеременная может иметь только три типа – целочисленная макропеременная INEGER4 (dword), целочисленная макроконстанта или текстовой макро (строковая макропеременная).

Автор считает значительным упущением отсутствия возможности определять тип макропеременной. Это очень сильно ограничивает возможности макропрепроцессора. Но что поделать.

При чём, в зависимости от вида определения макропеременной ML считает, что:

Как вы уже догадались, каждое макроопределение обладает своими свойствами и возможностями.

  1. Целочисленная макропеременная. Имеет тип INT (dword). Может участвовать во всех арифметических выражениях MASM. Как переменная она может изменять своё значение.
  2. Макроконстанта может иметь целочисленное значение. Её значение не может быть повторно изменено.
  3. Текстовой макро может быть любой строкой не более 255 символов. Поскольку он имеет статус переменной, его значение может быть изменено.

А теперь подробнее. Если с целочисленными макропеременными в достаточной степени ясно. То с определениями EQU полный бардак.

Как и в случае с вызовами макро, автор попытается построить алгоритм анализа EQU выражений:

1. Анализируем правую часть. В анализе правой части препроцессор выделяет лексемы, которые классифицирует как числа, строки. Так, например, в выражении:

«1234567890» – это лексема число, а «string1» – это строка, «macrofun()» – это всё равно строка (а не макрофункция. ).

Именно по этому такое определение будет давать ошибку:
qqqq EQU 156n7
: error A2048: nondigit in number

2. Если правая часть является верным определением числа в MASM, то есть 123 или 123h или 0101b – выполнить шаг три, иначе шаг четыре.

Обратите внимание, что числа с плавающей запятой в этом случае считаются строкой.

Такое поведение связано с внутренней организацией препроцессора ML, который просто «не понимает» чисел с плавающей запятой, и не умеет с ними работать.

То есть тип макропеременной Float:

будет не числовой, а строковой

3. Если полученное число имеет значение, не превышающее диапазон значений для dword – это целочисленная макроконстанта.

Если правая часть для EQU является верным числом более 25 символов, выдаётся ошибка:
: error A2071: initializer magnitude too large for specified size

При чём такая ошибка появляется даже в том случае, если выражение содержит другие символы через пробел:

Это объясняется действиями в пункте 1, когда ML анализирует лексемы. Кроме того, если числовая лексема не соответствует правилам определения чисел в ML, то есть в середине числа появляется символ A-Z, либо другие символы, не входящие в разряд разделителей – то такая лексема порождает ошибку, даже если она содержит число большее dword диапазона.

4. Иначе – это строковая макропеременная.

Теперь попробуйте самостоятельно определить тип макроопределения:

В данном примере только второй и третий вариант – макроконстанта, остальные – текстовые макро. Последний вариант таким не является, так как превышает диапазон значений для dword.

Замете, что поскольку препроцессор в правой части выделяет корректные выражения, правая часть не может состоять из недопустимых символов. Но при этом она может состоять из директивы определения литерала: «<>» – угловых кавычек.

Директива – определяет литерал, таким образом, указывая препроцессору ML, что он должен воспринимать нечто как строку символов. При этом сами «<>» – в строку не попадают. Директива <> – является единственной директивой для препроцессора ML, которая определяет литералы.

Именно по этой причине, все виды кавычек – двойные, одинарные, ` – вот такие одинарные, воспринимаются как простые символы, и как следствие проходят к значениям параметров макро. То есть, например:
MyMacro “Привет, это строка в двойных кавычках”
MyMacro ‘Привет, это строка в одинарных кавычках’
MyMacro `Привет, это строка в специальных кавычках`
MyMacro «Привет, это строка»‘И это’

И замете, что во всех случаях кавычки так же попадают в значения формального параметра макро. Вы можете использовать этот факт, например, для того, чтобы менять поведение макро, в зависимости от типа кавычек обрамляющих строку.

Кроме директивы, определяющей литерал, препроцессор ML имеет свой ESC-символ (символ отмены). В отличие от С этот символ – «!». Он отменяет действие других символов ( , «, ‘, %, ; , а так же символ запятой), которые могут иметь функциональность в том, или ином выражении. Если вы хотите получить «!», вы должны использовать последовательность «!!».

К сожалению, не обходится без проблем и с символом отмены «!». Восстановить точный алгоритм работы мне не удалось. Единственное, что возможно – это привести несколько примеров с непонятными эффектами при его использовании:

Вывод – не пользуйтесь директивой EQU для определения литералов, для этого есть другая директива – TEXTEQU.

Для директивы TEXTEQU алгоритм несколько отличен от алгоритма EQU, так как в TEXTEQU обрабатывается правое выражение на наличие символа %. То есть вы можете определить этот код:

На самом деле как вы видите, внутренняя работа TEXTEQU значительно отличается от EQU <>. Видимо по этому разработчики ML решили её ввести.

В руководстве MASM32 написано:
———————————————————————————————
The TEXTEQU directive acts like the EQU directive with text equates but performs macro substitution at assembly and does not require angle brackets. The TEXTEQU directive will also resolve the value of an expression preceded by a percent sign (%). The EQU directive does not perform macro substitution or expression evaluation for strings.
———————————————————————————————

Теперь вы должны понимать, что это не совсем так. Является ли это ошибкой разработчиков ML? Видимо да. В частности EQU не должна была переводить в статус переменных литералов определения типа:

И конструкция ниже должна была бы вызывать ошибку:

Но ошибка не появляется, более того значение literal меняется на dw

В заключении к этому пункту, вы должны осознать, что тип определений невозможно изменить. То есть переменная не может стать целочисленной константой:

Второе переопределение символа literal, не изменит его тип на тип целочисленной константы.

Думаю, у Вас возник вопрос:
– Что такое? Недокументированные возможности MASM?

У меня есть веские основания считать это ничем иным, как ошибкой разработчиков. Давайте предположим, что все макропеременные хранятся компилятором в памяти в виде массива структур. Не вдаваясь в подробности, пусть эта структура будет такая:

Как видно из структуры, значение макроконстанты может быть только dword’ом. Если это строка, то в поле value может быть записан указатель на строку (например, ASCIIZ).

Поле type может принимать только два значения, которое описывает тип value: либо value – содержит числовое значение макропеременной (константы).

Если определяется числовая константа то, вызывается одна функция (назовём её setmacrodefine_val()), которая добавляет в таблицу макроконстанту.

Это конечно предположение. И в действительности всё может быть ещё проще или ещё сложнее. Однако вероятность того, что свойства макропеременных хранятся именно подобным образом близка к единице. Теперь если вы немного подумаете, то поймёте:

Последний случай записывается в таблицу, как строковая макропеременная по той простой причине, что string не может быть записано в поле value, а поле type не имеет специального значения, чтобы указать, что value – это константный указатель на строку (помните C++?).

В конце концов, совершенно не важно угадал ли автор причину, или нет. Важно другое – что ошибка достаточно явная. А, кроме того, так и не была исправлена до сих пор (версия 7.0). Зато теперь вы сможет с пониманием отнестись к таким неожиданным эффектам.

Видимо разработчики не задумываются о том, что кто-то будет использовать определения MASM, иначе, нежели это написано в руководстве. И кому-то взбредёт в голову проверить, а можно ли переопределить EQU.

А подумайте, к каким бы серьёзным неуловимым ошибкам произвела бы эта халатность, если бы на MASM писали сложные приложения. Но как видно их никто не пишет.

Свои особенности имеют так же целочисленные выражения с оператором «=». В таких выражениях перед их выполнением осуществляется полная замена всех макроконстант, макропеременных на их значения, и вызов всех макрофункций.

Как вы думаете, что будет в следующем примере:

  1. Произойдёт ошибка переопределения константы.
  2. literal = 1234.

Второй вариант ответа мы должны откинуть сразу, потому что в этом пункте чётко определили, что данное переопределение невозможно. Первый вариант ответа больше похож на правду.… Однако не соответствует истине. Что же произошло? А произошло следующее:

  1. Препроцессор нашёл лексемы «literal» и «1234».
  2. Обнаружил, что «literal» является текстовым макро, и именно поэтому выполнил замену лексемы «literal» на её строковое значение.
  3. Проанализировал строку: «Something = 1234».

Этот факт может быть легко доказан, следующим тестом:

Если вас сбил с толку этот пример, не отчаивайтесь. Всё дело в том, что препроцессор ML в разных выражениях по-разному заменяет макропеременные. Вот об этом мы и поговорим в следующем пункте.

А пока подумайте, что должно случится в этом примере:

На этом можно было бы закончить данный пункт, если бы не одна особенность использования строк в вызове макро. А точнее приоритет анализа кавычек и директивы определения литерала <>. Не смотря на описанный выше алгоритм поведения макро, оказывается, что препроцессор при вызове макро выполняет определение литерала в кавычках, но что самое интересное, как было отмечено, выше сами кавычки попадают в строку. Если вам нужно передать макро одиночную кавычку вы должны воспользоваться символом отмены «!». Однако самое неприятное таится в том, что символы «<>» и кавычки конкурируют между собой в определениях строк. Например, попробуйте сказать, что должно было бы получиться в этом случае:

А можно было бы подумать, что ML должен принять операторы <> и запятую. Данное место – источник многих сложно обнаруживаемых ошибок. Например:

Если в строке попадается символ кавычки, а макропеременная char заменяется на значение кавычки, имеем:

В этом случае мы получаем ошибку:

Так и должно быть, потому что кавычки имеют высший приоритет анализа, чем оператор <>. Более того, угловые кавычки <> имеют самый низкий приоритет по отношению ко всем спец. символам, что согласуется с MASM Reference. Посмотрите на Дополнение к статье: пункт 3.a.i, который подозрительно выделен «жирным». В частности, следующее выражение, которое работает без проблем:

Появляется закономерный вопрос: для чего символ отмены «!»?
Данный пример демонстрирует скрытые глубины анализатора ML. А точнее его архитектурное несовершенство. Так как выражения с TEXTEQU как видно обрабатываются отдельной функцией, которая проверяет в первую очередь наличие угловых скобок «<>». Все другие выражения ML обрабатываются другой стандартной функцией, которая была написана задолго до появления TEXTEQU.

Замечательная наука всем программистам, которая демонстрирует, во что выливается халатность архитектора при дальнейших попытках расширения продукта.

Зато благодаря TEXTEQU пример с поиском символа в строке имеет решение:

Единственно, отчего не может помочь данный код – это от вылавливания в строке символов «> или », но при этом придётся отказаться от микроблока FORC.

III.3. Обработка выражения в MASM

MASM обрабатывает выражения в правой и левой части в зависимости от контекста. Там, где вам необходима предварительная обработка выражений, используется оператор «%». Он заставляет препроцессор ML сначала вычислить выражение после оператора % (то есть выражение в правой части относительно %), и только потом продолжить анализ всей строки. Например, если вы хотите, чтобы при вызове макро:

макропараметр был бы равен не строке «num», а значению текстового макро num, вы должны поставить оператор % перед num. Например:

Но и с оператором % не всё гладко.
Оказывается препроцессор ML, различает два (фактически три) вида выражений, в которых используется оператор %. Первый вид выражений – Арифметические:

Все выражения, содержащие операторы +,-,*, а так же сдвиговые и битовые операции

Все выражения результат вычисления которых – строка.

Так вот что интересно.

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

Левая часть = Правая часть
(Вызвать все макрофункции, и заменить все строковые макропеременные) = (Вызвать все макрофункции, и заменить все строковые и целочисленные макропеременные и константы)

В строковых выражениях происходит замена только строковых макропеременных (текстовых макро) (замете, что в ML нет строковых макроконстант). Это значит что в случае:

Появится: «PROGRAM_IMAGE_BASE», а не его числовое значение.

Однако есть и третий частный случай, когда оператор % относится только к одному литералу:

В этом случае происходит полный комплекс подстановок:

  1. Вызываются макрофункции.
  2. Заменяются все макропеременные или макроконстанты.

Значение literal будет подставлено в вызов макро, в независимости от того, какой тип имеет literal.

Выдержка их руководства MASM:
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
temp TEXTEQU %(SIZEOF array / LENGTHOF array)
% ECHO Bytes per element: temp

Note that you cannot get the same results simply by putting the % at the beginning of the first echo line, because % expands only text macros, not numeric equates or constant expressions.
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

Следует так же отметить, что в выражениях с exitm оператор % работает точно так же, как с выражениями в TEXTEQU.

III.4. Целочисленные выражения MASM

Целочисленные, побитовые операции так же необходимы разработчику макроопределений. Они дают возможность скрыть обработку битовых полей, или вычисление сложных выражений. Например, как это сделано в макрофункции $$$MAKELANGID.

Вы всегда должны помнить, что препроцессор MASM не различается знаковые и беззнаковые числа (подобно тому, как это делает x86), и значение числа не может выходить за диапазон dword. Препроцессор MASM не выдаёт предупреждений при переполнении. Следующий пример демонстрирует такое поведение:

В следующей статье мы поговорим про то, как работать с 64-bits макропеременными, используя данный факт.

Ниже приводится список операций, которые могут участвовать в целочисленных выражениях MASM.

Оператор Пример Описание
AND res = op1 AND op2 Операция логического «И» над каждым битом операндов op1 и op2.
OR res = op1 OR op2 Операция логического «ИЛИ» над каждым битом операндов op1, op2
NOT res = NOT op1 Операция логического «НЕ» над каждым битом операнда op1
XOR res = op1 XOR op2 Операция XOR между операндами op1, op2
SHL res = op1 SHL count Выполняет побитовый сдвиг влево (наподобие команды x86 shl) операнда op1, на количество бит, указанное в операнде count.
SHR res = op1 SHL count Выполняет побитовый сдвиг вправо операнда op1, на число бит, указанное в операнде count.
+,-,*,/ Основные математические операции
MOD res = op1 MOD op2 Возвращает остаток от деления операнда op1 на операнд op2
[] res = op1[op2] Операция: «Смещение». Выполняет сложение операндов op1 и op2

III.5. Вычисление рекурсивных выражений

Теперь, когда мы рассмотрели правила анализа и вычисления выражений в MASM, остаётся раскрыть важный вопрос: «Как происходит анализ выражений, если они состоят из других выражений?».

Обычно это называется короче: вложенные выражения.

Вложенное выражение – это такое выражение, элементы которого сами являются выражениями, которые так же могут иметь вложенность.

Замороченное определение, похожее на «Иди туда, не знаю куда, возьми то, не знаю что» – пример старинной народной русской рекурсии, которая так часто встречается в нашей жизни. )

Например, вызов макрофункции при вызове макро – это вложенное выражение:

Вложенность характеризуется параметром количества уровней вложенности. В недавнем примере уровень вложенности был равен двум. При чём вызов Fun2() можно называть выражением низшего уровня вложенности, а вызов макро MyMacro – выражением верхнего уровня.

После анализа выражений, и получения их многоуровневой структуры вложенности, препроцессор начинает вычислять результат выражения самого низшего уровня. Потом подставляет его результат в выражение следующего уровня, и так далее.

Например, для случая:

Порядок вычислений такой:

  1. %(12+34) = 46
  2. Fun2(46)
  3. FunMacro(MyCount = 46)
  4. Результат выполнения FunMacro(MyCount = 46)

А иначе препроцессор не смог бы. Если бы он начал вычисления выражений с верхнего уровня, то это то же самое, как если бы он попытался выполнить народную русскую рекурсию:
«Пойди туда, не знаю куда…, вычисли то, не знаю что»
или
FunMacro(. )

То есть: Вложенные выражения вычисляются последовательно от низшего уровня к верхнему, и результаты вычисления каждого уровня становятся материалом для выражений следующего уровня.

Это правило называется рекурсивным вычислением выражений. Оно используется везде, кроме мест вычисления значений макропараметров при вызове макро (как макросов, так и макрофункций). В этом случае действует правило: результат вложенного выражения присваивается макропараметру и не анализируется повторно. Это значит, что в данном примере:

вывод будет таким:

То есть препроцессор не будет снова вычислять выражение для второго макропараметра функции FunMacro(). Если бы он сделал это, то тогда вывод был бы таким, как в этом случае:

Теперь, когда вы знаете все тонкости вычисления выражений в MASM, настало время рассмотреть Встроенные макрофункции и директивы, которые участвуют в этих выражениях.

III.6. Встроенные макрофункции и директивы

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

MASM обладает несколькими встроенными макрофункциями, макропеременными и макроконстантами, которые работают так, как если бы они были макро, определённые вами. Вот список этих предопределений:

Возвращает строковое значение переменной среды окружения. Например:

Возвращает версию ML.

Имя макроопределения, его тип Описание
Определения Даты и Времени
@Date,
текстовое макроопределение (не макрофункция)
Возвращает строку вида MM/ДД/ГГ
Где:
MM – месяц, две цифры
ДД – день, две цифры
ГГ – год, две цифры
@Time,
текстовое макроопределение (не макрофункция)
Возвращает текущее время в 24-х часовом формате вида ЧЧ:ММ:СС
ЧЧ – часы, два числа
ММ – минуты, два числа
СС – секунды, два числа
Информация об окружении
@Cpu, числовая макроконстанта Битовая маска, определяющая режим работы процессора. Никакой информации о полях этой маски нет.
@Environ(env), макрофункция
@Interface, целочисленная макроконстанта Информация о языковых параметрах вызова.
@Version, строковая макроконстанта
Информация о файле
@FileCur, строковая макропеременная

Возвращает имя файла и путь к нему (если есть), так как был подан этот файл в командной строке компилятору ML.

@FileName, строковая макропеременная

Возвращает имя файла, без его расширения. То есть для модуля start.asm:

@Line, целочисленная макроконстанта

Возвращает номер текущей строки в файле.

Строковые макрофункции
@CatStr( string1 [[, string2. ]] ), макрофункция

Возвращает строку, созданную объединением строк параметров функции.

@InStr( [[position]], string1, string2 ), макрофункция

Возвращает позицию вхождения строки string2 в строку string1. Если параметр position определён, тогда поиск начинается именно с этой позиции. Отсчёт позиции начинается с единицы. В случае, если вхождение не найдено макрофункция возвращает значение . Параметр position должен быть целым числом больше нуля, но не равным нулю.

@SizeStr( string ) макрофункция Возвращает число, характеризующее длину строки, или, что тоже самое количество символов в строке. Функция возвращает число, однако, поскольку это макрофункция то тип возвращаемого значения – строка.
@SubStr( string, position [[, length]] ) макрофункция

Возвращает подстроку строки string, начиная с позиции, указанной в параметре position (отсчёт начинается с 1). Если необязательный параметр length задан, он ограничивает размер возвращаемой строки. Параметр length не может быть меньше нуля, и не может быть строкой.

Информация о сегментах
@code, строковая макропеременная Возвращает имя сегмента кода.
@data, строковая макропеременная

Возвращает модель памяти.

@fardata?, строковая макропеременная Равен имени сегмента FARDATA?
@WordSize, численная константа Содержит размер слова в байтах.
Для 16-bits – 2.
Для 32-bits – 4.
@CodeSize, численная константа Содержит идентификатор типа памяти.
0 – TINY, SMALL, COMPACT, FLAT.
1 – MEDIUM, LARGE, HUGE
@Model, численная константа 1 – TINY
2 – SMALL
3 – COMPACT
4 – MEDIUM
5 – LARGE
6 – HUGE
7 – FLAT
@CurSeg, строковая макропеременная Хранит имя текущего сегмента.
@fardata, @stack, строковая макропеременная Содержат соответствующие имена сегментов

Кроме знания макрофункций, нам так же понадобятся знания о блоках ветвлений или просто IF блоках. Эти блоки позволяют исполнять тот или иной участок исходного кода в зависимости от того, выполняется какое-либо условие или нет. Часто это называют «Условным ассемблированием (компиляцией)», однако для MASM это нечто большее, нежели простое управление компилятором, так как, вы уже поняли, мы имеем дело, как с кодом машины, так и с макрокодом, который вычисляется и живёт только во время компиляции.

Условный блок в MASM имеет следующий общий вид:

Если выражение «Условие» равно истине, то выполняется блок кода, идущий после условной директивы, иначе управление передаётся на следующий оператор за блоком. [IFDIRECTIVE]/[ELSEDIRECTIVE] – могут быть той или иной директивой условия. Стандартные директивы IF/ELSEIF/ELSE требуют, чтобы выражение, стоящее при них, было целочисленным. Если вам необходимо проверять другие условия, то для этого в MASM предусмотрены специальные директивы.

если идентификатор, который является результатом выражения, определен.

Идентификатором может быть макро, макропеременная, переменная, макроконстанта, любой другой идентификатор.

При помощи этой директивы, можно проверить была ли определена та или иная переменная, макро, константа.

Блок Условие выполнения блока
IF выражение
ELSEIF выражение
ELSE
если выражение равно истине
IF1
ELSEIF1
если ассемблер выполняет первый проход
IF2
ELSEIF2
если ассемблер выполняет второй проход (устарело)
IFE выражение
ELSEIFE выражение
если выражение равно нулю
IFDEF выражение
ELSEIFDEF выражение
IFNDEF выражение
ELSEIFNDEF выражение
если идентификатор не определён.
IFB строка
ELSEIFB строка

если строка пустая.

Строка считается пустой, если её длинна равна нулю, либо она содержит одни пробелы. С помощью этой директивы можно определяет присутствие/отсутствие необязательных макропараметров.

IFNB строка
ELSEIFNB строка
если строка не пуста.
IFDIF str1,str2
ELSEIFDIF str1,str2

если строки различны.

IFDIFI str1,str2
ELSEIFDIFI str1,str2

если строки различны (без учёта различий в регистре букв).

IFIDN str1,str2
ELSEIFIDN str1,str2

если строки одинаковы.

IFIDN str1,str2
ELSEIFIDN str1,str2

если строки одинаковы (без учёта различий в регистре букв).

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

Вы уже, наверное, убедились насколько полезна эта директива, позволяющая заглянуть, а что именно происходит в недрах макроса, или посмотреть значения макропеременных.

Кроме этого, есть ещё одна группа директив, без которой мы не сможем обойтись. Не сможем потому, что макрофункции, или макросы, которые мы собираемся создавать должны быть слегка умными, иначе говоря, иметь «защиту от дурака».

Если кто-то неправильно использует макрос, то код, полученный таким образом может быть неправильным с точки зрения программиста, но не вызовет подозрений у компилятора. Поэтому макро не просто должен завершится, а и каким-то образом остановить компиляцию программы с выдачей сообщения об ошибке.

Именно для этого и существует простой набор директив условной генерации ошибки. Действуют они подобно условным блокам и директиве echo. Пример безусловной генерации ошибки:

Условная генерация ошибки, имеют ту же форму, что и IFDIRECTIVE в таблице выше, однако последним дополнительным параметром является строка сообщения. Например:

III.7. Символ макроподстановки

Ещё раз вернёмся к формальным параметрам макро. Как было сказано, при раскрытии макроопределения препроцессор заменяет в теле макро формальные названия на их величины. В MASM32 предусмотрено ещё одно средство подстановки макропараметров – внутри строкового литерала.

Предположим нам нужно, чтобы макро генерировал строку: «label_xx». Где xx – это формальный параметр макро. Это можно сделать двумя способами:

То есть если во время генерации макро, препроцессор встречает в его теле символ «&», он анализирует строку после него. Если эта строка однозначно определяет один из макропараметров, препроцессор заменяет выражение &макропараметр& на значение макропараметра.

Следует отметить, что если макропараметр начинает или заканчивает литерал, то можно использовать только один символ «&»:

III.8. Макроблоки

И, наконец, у читателя должен остаться единственный вопрос: «А как обрабатывать переменные типа VARARG»? Например, рассмотрим возможный макро для вызова функций – STDCALL:

Этот макро должен генерировать код вызова функции согласно конвенции STDCALL:

  1. Поместить параметры в стек в обратном порядке их определению.
  2. Вызвать функцию funname, предварительно видоизменив её имя по правилам STDCALL.

Получить видоизмененное имя функции по значению параметра funname можно было бы при помощи символа макроподстановки.

Но непонятно, как распознать параметры функции, которые представляют собой строку, где значения разделены символом «,». Более того, не понятно, как вообще можно получить эти параметры, и посчитать их число, ведь макропараметр params – это одна строка. То есть при вызове макро:

Мы должны как-то определить количество параметров, а потом их значения.

Именно для решения этой задачи в MASM предусмотрены несколько специальных макроопределений, которые можно назвать макроблоками.

Первый из них FOR позволяет получить значения элементов, разделённых в строке символом «,».

Вспоминая С конструкцию FOR, вы сразу поймёте что это цикл, где значение parameter последовательно принимает значения элементов списка string.

Вот вам wonderful пример:

А вот пример макрофункции, который подсчитывает число аргументов VARARG:

Вот в принципе, уже на основе этих знаний можно было бы организовать макрос stdcall:

Ещё несколько минут необходимо для того, чтобы понять, что этот макро работает неправильно. Хотя бы потому, что параметры помещаются в стек не так. Нужно было бы помещать их от последнего к первому, а не от первого к последнему. А, кроме того, ведь символ макроподстановки нельзя употреблять к макропеременной count, потому что это не макропараметр, это макропеременная.

К сожалению, в MASM нет обратной конструкции FOR. Поэтому самый простой выход, который напрашивается сам собой – это изменить порядок параметров в списке, а потом только генерировать команды push.

Вторую проблему можно легко решить, воспользовавшись макрофункцией конкатенации строк:

С параметрами в стек будет посложнее. В принципе я бы решил эту задачу, если бы MASM поддерживал бы такой тип макропеременных как массив. Но хотя MASM и не поддерживает этот тип, его можно эмулировать.

Как вы можете догадаться, в этом примере создаются макропеременные varXX, которым присваиваются значения параметров. Теперь с той же лёгкостью можно работать с этими переменными. Можно снова использовать цикл FOR, однако в данном случае, было бы грамотней воспользоваться значением count, и выполнить цикл столько раз, сколько записано в нашем счётчике параметров. Для этого мы воспользуемся ещё одним макроблоком rept, о котором скажем позже:

Блок REPT выполняется столько раз, сколько указано в nparams. Я ввёл эту дополнительную макропеременную, для того, чтобы значение, указанное в REPT осталось неизменным. Однако этого не нужно. Можно было бы написать и так:

Значение макропеременной count инициализирует цикл только один раз вначале, после чего, она может, как угодно менять значение.

И ещё один макроблок, без которого нам невозможно будет реализовать макрос для определения строк уникода, или макрос, который позволяет писать строки OEM в редакторе использующий кодировку win cp-1251 (например, при создании консольных приложений).

Этот макроблок FORC:

Блок FORC выполняется столько раз, сколько символов в строке string, при этом макропараметр char равен текущему символу из строки.
Например, посчитать количество символов в строке можно было бы так:

А вот так, можно было бы посчитать количество пробельных символов.

TheSvin‘у, как и любому программисту, который часто имеет дело с битами, было бы удобно записывать значения бит по группам, через пробел.

Хорошо бы было написать некую макрофункцию, которая смогла бы позволить записывать эти выражения:

Напишите такую макрофункцию, которая позволила бы это делать. Напишите её для первого и второго вариантов исполнения.

III.9. Отладка макроопределений и заключение

А напоследок… остаётся маленькая деталь.

И эта деталь не самая приятная. Отладка макроопределений и их испытания невозможны под отладчиком. А, кроме того, если при генерации макро возникает ошибка, то ML выдаёт её в жутком виде:

То есть он выдаёт относительную строку в макро MacroLoop(3), где эта ошибка появилась. А если ещё макровызовы будут вложенными, то вам лучше не видеть этой замечательной картины.

Единственной возможностью качественно и относительно легко отлаживать макро – это употребление директивы echo.

На протяжении статьи вы не раз наблюдали примеры её использования. Но я снова повторюсь:

Заметьте, чтобы вывести значение целочисленной макропеременной необходимо воспользоваться макрофункцией @CatStr(), и перед аргументом указать оператор %. Почему именно так обсуждалась в пункте III.2. Определение макро переменных и строк.

Теперь вы знакомы с теорией использования макроопределений в MASM32, и сможете смело приступать к разработке макро. Именно этим мы и займёмся в следующей практической части нашего руководства, а так же заполним некоторые пробелы, на которые не обратили внимания здесь.

III.10. Абстрактный алгоритм анализа строки MASM (Дополнение)

1. Определены таблицы элементов:

Таблица переменных Хранит сведения о всех переменных модуля
Таблица меток Хранит список меток в коде.
Таблица процедур Хранит таблицу и прототип процедур
Список ключевых слов KEYLIST Хранит список ключевых слов, на которые реагирует ML
Таблица макрофункций Хранит тело всех макро, их имена и тип: макрофункция, или макро. Список макропараметров
Таблица макросов -=-
Таблица макропеременных, или переменных времени компиляции Хранит тип макропеременной и её значение.
Всё остальное, что не включено

2. Начальное состояние анализа строки.

3. Читать поток символов, пока не встретится символ возврата каретки без предыдущего символа «/». Игнорировать часть строки после «;»

a. Определить наличие лексем первого уровня в строке:

i. Выделить все строковые литералы в кавычках, если только это не выражение с TEXTEQU и символ комментария «;»
ii. Строковые литералы:
iii. Численные литералы: 1234, 1234h, 01011b
iv. Правильные литералы: строка из символов «A-Z,a-z,_0-9», но не начинающаяся на цифру
v. Литералы разделители: «,.»
vi. Управляющие Литералы: «+-*» Правильные литералы: строка из символов «A-Z,a-z,_0-9», но не начинающаяся на цифру

b. Проверить правильные литералы на совпадение в списке ключевых слов, и определить схему выражения. В зависимости от схемы выражения, выполнить или пропустить:

i. Проверить правильные литералы на совпадение в списке макро (в зависимости от способа вызова в списке макрофункций, или макросов)
ii. Проверить на наличие имени правильного литерала в таблице макропеременных.
iii. Осуществить вызов и замену макро и макропеременных, в соответствии с выражением строки.
iv. Вычислить все выражения допустимые в ML (+-*).

c. Осуществить разбор схемы.

i. Если это определение процедуры, записать в таблице процедур имя и прототип новой процедуры
ii. Если это макроопределение: анализировать его тело. Если найден возвращаемый параметр, записать макроопределение в таблицу макрофункций, иначе в таблицу макросов.
iii. Если это определение EQU вычислить правую часть.

1. Если эта макропеременная уже есть в таблице макропеременных, и её тип – числовой, выдать ошибку. Если эта макропеременная имеет строковый тип, изменить строку, на которую указывает свойство value этой макропеременной.
2. Если правая часть числовой литерал – записать EQU определение в таблицу, и пометить его тип как числовой константы. Записать в свойство макропеременной value значение указателя на строку. Записать свойство value равным числу.
3. иначе EQU – переменная, имеющая указатель на строку. Записать в значения свойства value указатель на строку.

iv. Если это выражение с «=» или подобное, выполнить замену всех литералов на макроконстанты, переменные, вызов всех макрофункций, и только потом выполнять выражение.

4. Перейти к анализу следующей строки.

Источник

Adblock
detector

  • Remove From My Forums
  • Question

  • After installed SP1 in VS2008

    Linker -> Additional Dependencies -> msvcrt.lib

    Custom Build Step -> General -> Command Line ->
    ml -c -Zi «-Fl$(IntDir)$(InputName).lst» «-Fo$(IntDir)$(InputName).obj» «$(InputPath)»

    Custom Build Step -> General -> Outputs -> $(IntDir)$(InputName).obj

    app.config

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
      <dependency>
         <dependentAssembly>
           <assemblyIdentity
             type="win32"
             name="Microsoft.Windows.Common-Controls"
             version="6.0.0.0"
             processorArchitecture="X86"
             publicKeyToken="6595b64144ccf1df"
             language="*"
             />
           </dependentAssembly>
        </dependency>
      </assembly> 

    		.386
    		.model flat, c
    		.stack 100h
    printf	PROTO arg1:Ptr Byte, printlist:VARARG
    		.data
    msg1fmt byte "%s%d",0Ah,0
    msg1	byte "The answer is: ",0
    num1	sdword ?
    num2	sdword ?
    		.code
    main	proc
    		mov num1,5
    		mov eax,num1
    		mov num2,eax
    		INVOKE printf, ADDR msg1fmt, ADDR msg1, num2
    		ret
    main	endp
    		end

    		
    Command Lines      Creating temporary file "d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2DebugRSP00000624203512.rsp" with contents
    [
    /out:".DebugtestStandalone2.exe.embed.manifest" /notify_update /manifest
    ".DebugtestStandalone2.exe.embed.manifest"
    ]
    Creating command line "mt.exe @"d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2DebugRSP00000624203512.rsp" /nologo"
    Creating temporary file "d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2DebugBAT00000724203512.bat" with contents
    [
    @echo Manifest resource last updated at %TIME% on %DATE% > ".Debugmt.dep"
    ]
    Creating command line """d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2DebugBAT00000724203512.bat"""
    Creating temporary file "d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2DebugBAT00000824203512.bat" with contents
    [
    @echo off
    ml -c -Zi "-FlDebugtestStandalone2.lst" "-FoDebugtestStandalone2.obj" "d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj"
    if errorlevel 1 goto VCReportError
    goto VCEnd
    :VCReportError
    echo Project : error PRJ0019: A tool returned an error code from "Performing Custom Build Step"
    exit 1
    :VCEnd
    ]
    Creating command line """d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2DebugBAT00000824203512.bat"""
     Output Window      Embedding manifest...
    Performing Custom Build Step
     Assembling: d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(1) : error A2008:syntax error : ?xml version="1.0" encoding="big5"?
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(2) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(10) : error A2008:syntax error : >
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(11) : error A2008:syntax error : Platforms
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(12) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(14) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(15) : error A2008:syntax error : /Platforms
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(16) : error A2008:syntax error : ToolFiles
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(17) : error A2008:syntax error : /ToolFiles
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(18) : error A2008:syntax error : Configurations
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(19) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(25) : error A2008:syntax error : >
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(26) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(28) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(29) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(33) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(34) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(36) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(37) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(39) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(40) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(42) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(43) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(53) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(54) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(56) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(57) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(59) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(60) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(62) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(63) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(71) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(72) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(74) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(75) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(77) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(78) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(80) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(81) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(83) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(84) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(86) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(87) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(89) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(90) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(92) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(93) : error A2008:syntax error : /Configuration
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(94) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(101) : error A2008:syntax error : >
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(102) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(104) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(105) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(107) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(108) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(110) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(111) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(113) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(114) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(116) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(117) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(127) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(128) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(130) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(131) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(133) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(134) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(136) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(137) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(145) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(146) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(148) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(149) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(151) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(152) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(154) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(155) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(157) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(158) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(160) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(161) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(163) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(164) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(166) : error A2008:syntax error : /
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(167) : error A2008:syntax error : /Configuration
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(168) : error A2008:syntax error : /Configurations
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(169) : error A2008:syntax error : References
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(170) : error A2008:syntax error : /References
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(171) : error A2008:syntax error : Files
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(172) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(176) : error A2008:syntax error : >
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(177) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(179) : error A2008:syntax error : >
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(180) : error A2008:syntax error : /File
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(181) : error A2008:syntax error : /Filter
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(182) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(186) : error A2008:syntax error : >
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(187) : error A2008:syntax error : /Filter
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(188) : error A2045:missing angle bracket or brace in literal
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(192) : error A2008:syntax error : >
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(193) : error A2008:syntax error : /Filter
    d:DataMy DocumentsVisual Studio 2008ProjectstestStandalone2testStandalone2testStandalone2.vcproj(194) : fatal error A1012:error count exceeds 100; stopping assembly
    Microsoft (R) Macro Assembler Version 9.00.30729.01
    Copyright (C) Microsoft Corporation.  All rights reserved.
    Project : error PRJ0019: A tool returned an error code from "Performing Custom Build Step"
     


    我要呢個女人賠醫藥費

    • Edited by

      Monday, April 30, 2012 6:27 AM

Answers

  • It looks like the ml tries to compile the .vcproj file :)   Nothing good can come out of this, obviously.

    Review and fix your project settings, especially what is $(InputPath).

    — pa

    • Proposed as answer by
      Helen Zhao
      Monday, May 7, 2012 9:08 AM
    • Marked as answer by
      Helen Zhao
      Tuesday, May 8, 2012 6:00 AM

  • Hi TorFree,

    As far as I know, PRJ0019 may occur when a tool returned an error code but no error message. This can happen, for example, if you redirect the output of MIDL to NUL. This error can also occur when you are running as a member of the Users group and Administrative
    access is needed.

    If your custom build steps or events are not behaving as you expect, there are several things you can do to try to understand what is going wrong.

    1->Make sure that the files your custom build steps generate match the files you declare as outputs.
    2->If your custom build steps generate any files that are inputs or dependencies of other build steps (custom or otherwise), make sure that those files are added to your project. And make sure that the tools that consume those files execute after the custom
    build step.
    3->To display what your custom build step is actually doing, add @echo on as the first command. The build events and build steps are put in a temporary .bat file and run when the project is built. Therefore, you can add error checking to your
    build event or build step commands.
    4->Examine the build log in the intermediate files directory to see what actually executed. The path and name of the build log is represented by the
    MSBuild macro expression, $(IntDir)$(MSBuildProjectName).log.
    5->Modify your project settings to collect more than the default amount of information in the build log. On the
    Tools menu, click Options. In the Options dialog box, click the
    Projects and Solutions node and then click the Build and Run node. Then, in the
    MSBuild project build log file verbosity box, click Detailed.

    6->Verify the values of any file name or directory macros you are using. You can echo macros individually, or you can add
    copy %0 command.bat to the start of your custom build step, which will copy your custom build step’s commands to command.bat with all macros expanded.
    7->Run custom build steps and build events individually to check their behavior. 

    If you want to know more information about this issue, please refer to the following links:

    http://msdn.microsoft.com/en-us/library/yzk29wdw.aspx
    http://msdn.microsoft.com/en-us/library/b0bktkzs(v=vs.100).aspx

    Best regards,
    Helen Zhao


    Helen Zhao [MSFT]
    MSDN Community Support | Feedback to us

    • Proposed as answer by
      Helen Zhao
      Monday, May 7, 2012 9:08 AM
    • Marked as answer by
      Helen Zhao
      Tuesday, May 8, 2012 6:00 AM

KnowledgeBase Archive

An Archive of Early Microsoft KnowledgeBase Articles

View on GitHub


Article: Q75601
Product(s): Microsoft Macro Assembler
Version(s): MS-DOS:5.10a,6.0,6.0a,6.0b,6.1,6.10a,6.11
Operating System(s): 
Keyword(s): 
Last Modified: 06-MAY-2001

-------------------------------------------------------------------------------
The information in this article applies to:

- Microsoft Macro Assembler (MASM), versions 5.10a, 6.0, 6.0a, 6.0b, 6.1, 6.10a, 6.11 
-------------------------------------------------------------------------------

SYMPTOMS
========

When initializing a structure in the Microsoft Macro Assembler (MASM), if the
initializers are written on separate lines, one or more of the following errors
may occur:

  MASM 6.x A2045: missing angle bracket or brace in literal
  MASM 6.x A2009: syntax error in expression
  MASM 5.x A2105: expected: instruction, directive or label

RESOLUTION
==========

To work around this problem, either use the backslash () line continuation
character following a comma, or with MASM 6.0 and later use curly braces in
place of the angle brackets. Curly braces are a legal substitute syntax for
angle brackets. The sample code below illustrates the problem syntax and the
workaround.

STATUS
======

Microsoft has confirmed this to be a problem in MASM versions 5.1, 5.1a, 6.0,
6.0a, 6.0b, 6.1, 6.1a, and 6.11. We are researching this problem and will post
new information here in the Microsoft Knowledge Base as it becomes available.

MORE INFORMATION
================

Page 127 of the "Microsoft Macro Assembler Programmer's Guide" from MASM 6.0
states:

  The list of initializers can be broken only after a comma unless you use a
  line continuation character () at the end of the line.

The following sasmple code can be used to demonstrate the problem.

Sample Code
-----------

  ; Assemble options needed: /c

  .MODEL small

  name1 STRUCT
     sub1 DB 'item'
     sub2 DW ?
  name1 ENDS

  .DATA
  ;item3 name1 {'am',     ; assembles correctly
  ;             14}

  ;item4 name1 <'pm',    ; assembles correctly with the
  ;             18>       ; ()continuation character

  item3 name1 <'am',      ; this generates an error
               14>        ; MASM 6.0 A2045: missing angle bracket or
                          ; brace in literal
                          ; MASM 5.1 A2105: expected: instruction,
                          ; directive or label

  item4 name1 <'pm'      ; this generates an error
               18>        ; MASM 6.0 A2009: syntax error in expression
                          ; MASM 5.1 A2105: expected: instruction,
                          ; directive or label
  .CODE
     mov ax, @data        ; initialize the ds register
     mov ds, ax
     mov ax, item3.sub2   ; for verifying the values
     mov ax, item4.sub2   ; of the initialization, in CodeView
     mov ax, 4C00h
     int 21h
  END

Additional query words: 5.10 5.10a 6.00 6.00a 6.00b 6.10 6.10a buglist6.00a buglist6.00b buglist6.10 buglist6.10a buglist6.11

======================================================================
Keywords          :  
Technology        : kbMASMsearch kbAudDeveloper kbMASM600 kbMASM610 kbMASM611 kbMASM600a kbMASM600b
Version           : MS-DOS:5.10a,6.0,6.0a,6.0b,6.1,6.10a,6.11

=============================================================================

THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS
PROVIDED «AS IS» WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS
ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO
EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR
ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL,
CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF
MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION
OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES
SO THE FOREGOING LIMITATION MAY NOT APPLY.

Copyright Microsoft Corporation 1986-2002.

Topic: A problem with a macro  (Read 10950 times)

Hi all,
        In the folowing macro if we do

                SETRECORDSIZEMACRO  1000

                it doesn´t assemble. We wait and nothing!

        Is there a best way to implement it ?
        Thanks

SETRECORDSIZEMACRO  MACRO   kInt

                    IF  kInt LE $RECORDSIZE_256

                        IF  kInt EQ $RECORDSIZE_32

                            LenOfRecords equ $RECORDSIZE_32
                            $RECORDSIZE  equ $SHLRECORDSIZE_32

                        ELSEIF  kInt EQ $RECORDSIZE_64

                                LenOfRecords equ $RECORDSIZE_64
                                $RECORDSIZE  equ $SHLRECORDSIZE_64

                                                        ELSEIF  kInt EQ $RECORDSIZE_128

                                LenOfRecords equ $RECORDSIZE_128
                                $RECORDSIZE equ $SHLRECORDSIZE_128
                        ELSE                                   
                                LenOfRecords equ $RECORDSIZE_256
                                $RECORDSIZE  equ $SHLRECORDSIZE_256
                        ENDIF
                    ;---------------------------------------------------
                    ELSEIF  kInt EQ $RECORDSIZE_512

                            LenOfRecords equ $RECORDSIZE_512
                            $RECORDSIZE  equ $SHLRECORDSIZE_512

                    ELSEIF  kInt EQ $RECORDSIZE_1024

                            LenOfRecords equ $RECORDSIZE_1024
                            $RECORDSIZE  equ $SHLRECORDSIZE_1024

                    ELSEIF  kInt EQ $RECORDSIZE_2048

                            LenOfRecords equ $RECORDSIZE_2048
                            $RECORDSIZE  equ $SHLRECORDSIZE_2048

                    ELSE                               
                            LenOfRecords equ $RECORDSIZE_4096
                            $RECORDSIZE  equ $SHLRECORDSIZE_4096
                    ENDIF

                                        $RECORDSIZE4    = $RECORDSIZE / 4                   
ENDM


Logged


SETRECORDSIZEMACRO  MACRO

SETRECORDSIZEMACRO 1000 works for me.


Logged


I guess that kInt should be round up to the next higher power of two. e.g.:

SETRECORDSIZE MACRO   kInt
IF kInt LE 0
.err <what ever>
EXITM
ENDIF

srs_val = kInt
.radix 2
srs_txt TEXTEQU %srs_val
.radix 10
srs_log2p1 SIZESTR srs_txt
srs_pow2 = 1 SHL (srs_log2p1-1)
IF srs_val NE srs_pow2
IF srs_pow2 EQ 80000000h
.err <value to large>
ENDIF
srs_pow2 = srs_pow2 * 2
ENDIF

%echo _kInt=kInt --> @CatStr(%srs_pow2)
;LenOfRecords = srs_pow2 ???
ENDM


Logged

MREAL macros — when you need floating point arithmetic while assembling!


 

:greensml:
Jochen,
        The name is a name and
        i called «SETRECORDSIZEMACRO».
        Why not? Where is a different rule ?
        Thank you Jochen !  :t

qWord,
«I guess that kInt should be round up to the next higher power of two»
Yes, of course, you know!

        I tried to undestand what you did
        and i am close.
        Ok, LenOfRecords is srs_pow2. But
        i need the exponent also to
        the variable $RECORDSIZE.
        If kInt = 512 = 2^9 we must get
        $RECORDSIZE = 9.
        Could you do it ?
        Thank you qWord !  :t


Logged


I tried to undestand what you did
        and i am close.
        Ok, LenOfRecords is srs_pow2. But
        i need the exponent also to
        the variable $RECORDSIZE.
        If kInt = 512 = 2^9 we must get
        $RECORDSIZE = 9.
        Could you do it ?

The trick is to convert the integer value to a string literal in base 2. The size of that string can be used to get the binary logarithm (more detailed: string size = Floor(log2(x))+1).
Thus the binary exponent is: srs_log2p1-1


Logged

MREAL macros — when you need floating point arithmetic while assembling!


Ok, i will try it tomorrow
Thanks :t
Meanwhile i tried with 4000
and i got the same problem.
It has nothing to do with that macro.
The problem seems to be here:

MemForRecords       equ AllocRecords * LenOfRecords
                ;»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
                ; The memory structure for linked list,
                ; must be defined in .DATA in this way:
                ;»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»

                dq NumOfLkdFields dup(0)
                ;
                dd 0                  ; 44 for pNewRecordLIST   => for current record pointer               
                dd 0                  ; 40 for NewallocLIST     => current alloc
                dd 0                  ; 36 for FindFlagLIST     => find flag
                dd 1                  ; 32 for IDXallocLIST     => alloc first record
                ;
                dd offset _FrmRecord  ; 28 for pFrmRecordLIST   => for record format
                dd 0                  ; 24 for SizeStringLIST   => any string length                 
                dd 0                  ; 20 for NumRecordsLIST   => number of records in the list
                dd NumOfFields        ; 16 for NumFieldsLIST    => number of fields
                dd LenOfRecords       ; 12 for SizeRecordLIST   => size of each record
                dd AllocRecords       ;  8 for TotRecordsLIST   => number of allocated records
                dd 0                  ;  4 for pMemallocLIST    => memory pointer
;_LkdDataABase   db MemForRecords dup(?)


Logged


sorry, forgot the case when the pwr2 is doubled  :redface:
should be something like:

SETRECORDSIZE MACRO   kInt
IF kInt LE 0
.err <what ever>
EXITM
ENDIF

srs_val = kInt
.radix 2
srs_txt TEXTEQU %srs_val
.radix 10
srs_log2p1 SIZESTR srs_txt
srs_pow2 = 1 SHL (srs_log2p1-1)
IF srs_val NE srs_pow2
IF srs_pow2 EQ 80000000h
.err <value to large>
ENDIF
srs_pow2 = srs_pow2 * 2
srs_log2p1  = srs_log2p1  + 1 ;; update log2
ENDIF
$RECORDSIZE = srs_log2p1 - 1
LenOfRecords = srs_pow2
ENDM


Logged

MREAL macros — when you need floating point arithmetic while assembling!


:greensml:
Jochen,
        The name is a name and
        i called «SETRECORDSIZEMACRO».
        Why not? Where is a different rule ?

Rui,
There is no such rule, but when you wrote «it doesn’t assemble», I thought it might have been one «MACRO» too much ;-)


Logged


Rui,
There is no such rule, but when you wrote «it doesn’t assemble», I thought it might have been one «MACRO» too much ;-)

Jochen,
             i understood exactly what you say here. I was kidding with you !  :biggrin:


Logged


qWord,
        First of all, thank you so much !  :t
        Now, some questions. The first is this:

        When i do: 
                            SETRECORDSIZE  -200
        i get:

Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997.  All rights reserved.

 Assembling: ...LinkedList12LkdList10.asm
...LinkedList12LkdList10.prj(103) : error A2045: missing angle bracket or brace in literal
 SETRECORDSIZE(3): Macro Called From
...LinkedList12LkdList10.prj(103): Include File
_
Assembly Error

       
        It seems to mean that we dont need to do

                    IF kInt LE 0
            .err <what ever>
            ENDIF       

        But, meanwhile, you are a gentle man !       
        replace it by this:

   IF kInt LE 0
             .err <Hey, bear! it cannot be a negative number!>
   ENDIF       

        What do you say about this ?


Logged


The exclamation mark has a special meaning in angle brackets: the character flowing the «!» is treaded as literal in any case.  Because of that, the closing  «>» is recognized as part of the string and MASM complains about the missing bracket.

.err @CatStr(<Hey, bear!! it cannot be a negative number!!>)


Logged

MREAL macros — when you need floating point arithmetic while assembling!


 

:biggrin:
Hi qWord,
            It works very well.  ;)
            Thank you so much.  :t

%%%%%%%%%%%%%%%%%%%%%%%%
i am learning something about MACROS with you
%%%%%%%%%%%%%%%%%%%%%%%%

    note: i followed your explanation.

        I took your macro and i did this

        COMPUTERECORDSIZE kInt

COMPUTERECORDSIZE   MACRO   kInt

                  IF kInt LE 0
                        .err <Hey, bear, it cannot be a negative number>
            EXITM
                    ELSE

                                            ;; iInt = kInt
                        ;; IF iInt LE 16

                                                                       IF kInt LE 16

                            ;;------------------------------------------------
                            ;;set it to 32 because the structure needs 8 bytes
                            ;;  so the length for anything is only 8 bytes
                            ;;          if we choose kInt=1 to 16
                            ;;------------------------------------------------

                            ;;iInt = 32

                            kInt = 32                           

                        ENDIF                   
              ENDIF

                    ;;------------------------------------------
                    ;; convert kInt into a decimal value srs_val
                    ;;------------------------------------------
              srs_val = kInt                      ;; value of kInt
              ;; srs_val = iInt                      ;; value of kInt

                    ;;------------------------------------------
                    ;; Take Base 2 and convert the value srs_val
                    ;;         to a text "string" srs_txt
                    ;;------------------------------------------
              .radix 2
        srs_txt TEXTEQU %srs_val            ;; string of binary digits

                    ;;------------------------------------------
                    ;; Take Base 10 and get the size of srs_txt.
                    ;; The most significant bit is at position
                    ;;        size of srs_txt - 1     
                    ;;------------------------------------------
              .radix 10

               sizebinarytext SIZESTR srs_txt      ;; size of it = number of binary digits

                    ;;------------------------------------------
                    ;; $RECORDSIZE is the exponent of power 2^x
                    ;;    To multiply by LenOfRecords we do
                    ;;           SHL  by $RECORDSIZE
                    ;;------------------------------------------
                    $RECORDSIZE   = sizebinarytext - 1   ;; exponent of 2^
                    LenOfRecords = 1 SHL $RECORDSIZE     ;; length of each record

              IF srs_val NE LenOfRecords

          IF LenOfRecords EQ 80000000h
       .err <value to large>
          ENDIF

                      ;;-----------------------------------------
                      ;;       set the next LenOfRecords
                      ;;-----------------------------------------
       LenOfRecords = LenOfRecords * 2
                      $RECORDSIZE  = $RECORDSIZE + 1

                      ;;------------------------------------------------
                      ;; $RECORDSIZE  is used to get each record pointer
                      ;; LenOfRecords is used to alloc memory for
                      ;;               the database
                      ;;------------------------------------------------
                %echo LenOfRecords=kInt --> @CatStr(%LenOfRecords)
                %echo $RECORDSIZE =kInt --> @CatStr(%$RECORDSIZE)

              ENDIF
ENDM

Example of what we are doing above

———————————
For numbers from 32 to 63
        ‘0’ is any x
———————————

                       5  4  3  2  1  0    <- position
;————————————————                                       
32   = 2^5  =    1  0  0  0  0  0B   => size =6   =>  size-1 = 5
                     ———————-
                     ———————-
                                            1    -> if we shift left this «1» by 5
                        1  0  0  0  0  0    <- we get this, which is =32 !

log2(2^5)= 5 = size-1

+++++++++++++++++++++++++++++
           now i have this problem
+++++++++++++++++++++++++++++

When i use iInt 
       and
           COMPUTERECORDSIZE 15

     i dont get the echo:

             LenOfRecords=15 —> 16
        $RECORDSIZE =15 —> 4

    Why ?
——————————————————
When i use kInt 
       and
           COMPUTERECORDSIZE 15           <—- is in .prj(98)
       i get this:

Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997.  All rights reserved.

 Assembling: …LinkedList12LkdList10.asm
…LinkedList12LkdList10.prj(98) : error A2008: syntax error : integer
 COMPUTERECORDSIZE(18): Macro Called From
…LinkedList12LkdList10.prj(98): Include File
LenOfRecords=15 —> 16
$RECORDSIZE =15 —> 4
_
Assembly Error
Prima qualquer tecla para continuar . . .


Logged


The macro parameters are not variables, they are placeholders for text replacement. Before «executing» the macro, MASM does search for the parameter IDs in the macro body and replace all occurrences with the corresponding text from the macro call. Thus «kInt = 32» becomes «15 = 32» after text replacement (for COMPUTERECORDSIZE 15). To solve the problem, just move the equate initialization (srs_val = kInt) at top of the macro and overwrite it if needed. Also remarks that there are ELSEIF-clauses, which makes live easier: «ELSEIF kInt LE 16»


Logged

MREAL macros — when you need floating point arithmetic while assembling!


The macro parameters are not variables,
they are placeholders for text replacement.
Before «executing» the macro, MASM does search for the parameter IDs in the macro
body and replace all occurrences with the corresponding text from the macro call.

Thus the «kInt = 32» becomes «15 = 32» after text replacement.

It seems to mean this (more or less) by other words :
-Redefinitions of input parameters
 are not allowed because…

Now, using your hint, just as you said:

       and
             COMPUTERECORDSIZE 15

        i don’t get the echo:

                  LenOfRecords=15 —> 16
             $RECORDSIZE =15 —> 4

        The question is: why ?
        I know that Len…=32 and $REC…=5

COMPUTERECORDSIZE   MACRO   kInt
                    ;;------------------------------------------
                    ;; convert kInt into a decimal value srs_val
                    ;;------------------------------------------
              srs_val = kInt                      ;; value of kInt

                  IF kInt LE 0
                        .err <Hey, bear, it cannot be a negative number>
            EXITM

                    ELSEIF kInt LE 16
                        ;;---------------                       
                        ;; set it to 32
                        ;;---------------
                        srs_val = 32                           
              ENDIF

                    ;;------------------------------------------
                    ;; Take Base 2 and convert the value srs_val
                    ;;         to a text "string" srs_txt
                    ;;------------------------------------------
              .radix 2
        srs_txt TEXTEQU %srs_val            ;; string of binary digits

                    ;;------------------------------------------
                    ;; Take Base 10 and get the size of srs_txt
                    ;; the most significant bit is at position
                    ;;        size of srs_txt - 1     
                    ;;------------------------------------------
              .radix 10

               sizebinarytext SIZESTR srs_txt      ;; size of it = number of binary digits

                    ;;------------------------------------------
                    ;; $RECORDSIZE is the exponent of power 2^x
                    ;;    To multiply by LenOfRecords we do
                    ;;           SHL  by $RECORDSIZE
                    ;;------------------------------------------
                    $RECORDSIZE   = sizebinarytext - 1   ;; exponent of 2^
                    LenOfRecords = 1 SHL $RECORDSIZE     ;; length of each record

              IF srs_val NE LenOfRecords

          IF LenOfRecords EQ 80000000h
       .err <value to large>
          ENDIF

                      ;;-----------------------------------------
                      ;;       set the next LenOfRecords
                      ;;-----------------------------------------
          LenOfRecords = LenOfRecords * 2
                      $RECORDSIZE  = $RECORDSIZE + 1

                      ;;------------------------------------------------
                      ;; $RECORDSIZE  is used to get each record pointer
                      ;; LenOfRecords is used to alloc memory for
                      ;;               the database
                      ;;------------------------------------------------
                %echo LenOfRecords=kInt --> @CatStr(%LenOfRecords)
                %echo $RECORDSIZE =kInt --> @CatStr(%$RECORDSIZE)

              ENDIF
ENDM

         
Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997.  All rights reserved.

 Assembling: …LinkedList12LkdList10.asm
Microsoft (R) Incremental Linker Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

 O volume na unidade C não tem nome
 O número de série do volume é …

 Directório de …LinkedList12

05-06-2014  11:26           100.768 LkdList10.asm
04-06-2014  17:07            37.330 LkdList10.cnv
04-06-2014  17:07            14.190 LkdList10.dat
05-06-2014  10:32            23.828 LkdList10.deb
04-06-2014  17:07             2.451 LkdList10.equ
05-06-2014  17:40            52.224 LkdList10.exe
04-06-2014  17:07            19.191 LkdList10.frm
04-06-2014  17:08             7.038 LkdList10.glb
04-06-2014  18:14           250.339 LkdList10.inc
05-06-2014  17:40            45.327 LkdList10.mac
05-06-2014  17:40           107.761 LkdList10.obj
05-06-2014  16:30             8.225 LkdList10.prj
04-06-2014  17:09             3.784 LkdList10.pro
04-06-2014  17:50            16.115 LkdList10.txt
              14 ficheiro(s)          688.571 bytes
               0 Dir(s)        44.560.060.416 bytes livres
Prima qualquer tecla para continuar . . .


Logged


It seems to mean this (more or less) by other words :
-Redefinitions of input parameters
 are not allowed because…

It is no redefinition — the identifier «kInt» is replaced by «15» when you call «COMPUTERECORDSIZE 15». Macro parameters are always treaded as strings/text — in your case the string is a numeric literal «15». In contrast to that, equates assigned with = are internally represented as binary values. The conversion from numeric literals (=strings) to equates is implicit done when using the «=» operator. However, converting equates to numeric literals (=string/text) requires the expansion operator «%».
For example:

foo = 123456 ; assign value
COMPUTERECORDSIZE %foo
Due to the expansion operator, the equate «foo» is converted to the string «123456», which is then used for text replacement in the macro body.[1]
For

COMPUTERECORDSIZE foothe string «foo» is used for replacement in the macro body. This, for example, means the that «kInt = 32» becomes «foo = 32», which is valid. It is not wise to design macros in this way, because it requires that the corresponding macro parameter are equates.
Just as side note, remarks that macro parameters are trimmed (unless using angle brackets).

i don’t get the echo …  why ?

Because the ECHO directives are placed inside the conditional block «IF srs_val NE LenOfRecords».

[1]The expansion operator does assume singed integer values. However, when using % with TEXTEQU/CATSTR/INSTR/SUBSTR or EXITM, the values are treaded as unsigned integers. For example «xyz TEXTEQU %(-1)» does assign the string «4294967295» to the text macro xyz (the expression «(-1)» does produce a temporary equate, btw).


Logged

MREAL macros — when you need floating point arithmetic while assembling!


Руководство по проектированию макросов в MASM32

Дата публикации 25 авг 2003

Руководство по проектированию макросов в MASM32 — Архив WASM.RU

Руководство по проектированию макросов в MASM32

Edmond / HI-TECH

Руководство по проектированию макросов в MASM32

Пойми в Хаосе Разное, и стань человеком.
Осознай Единое в Различном – и будь Богом.

Автор

I. От автора
I.1. Для тех, кто впервые
I.2. Примечания (обо всём понемногу)
I.3. Особенности терминологии
I.4. Благодарности
II. Лень – двигатель Макро
III. Макромир MASM
III.1. Функционирование макросов
III.2. Определение макро переменных и строк
III.3.
Обработка выражения в MASM
III.4. Целочисленные выражения MASM
III.5. Вычисление рекурсивных выражений
III.6. Встроенные макрофункции и директивы
III.7. Символ макроподстановки
III.8. Макроблоки
III.9. Отладка макроопределений и заключение
III.10. Абстрактный алгоритм анализа строки MASM (Дополнение)

I. От автора

В этом руководстве раскрывается тема создания, использования (а главное –
проектирования) макросов и макрофункций в проектах на MASM32.

Что не так важно в ЯВУ, то очень важно в программировании на ассемблере.
Если выстроить по приоритетам недостатки программирования на ассемблере,
то первым
недостатком будет не объём строк написанного кода (как нестранно), а отсутствие
средств, обеспечивающих хороший стиль написания кода.

Что значит стиль? А что значит плохой или хороший? Это можно быстро понять
на простом примере.

Допустим, у вас есть процедура объёмом на несколько экранов. Вы её написали
месяц назад, а теперь вам нужно несколько изменить её поведение. Для того,
чтобы сделать
это, вам необходимо:

  1. Вспомнить её алгоритм (если забыли)
  2. Вспомнить особенности реализации (у вас должны быть комментарии)
  3. Вспомнить какой участок кода, чем занимается.

Если код процедуры был прооптимизирован, вероятней всего вам захочется,
чтобы после модификации он остался настолько же оптимальным,
а поэтому вы должны
вспомнить все тонкости кода, или только того участка, который
подлежит модификации.

А это не так то просто, даже если исходник написан вами, в вашем
неповторимом стиле.

Если этот стиль будет хорошим, вы потратите меньшее время,
если бы стиль был бы плохим.

Хороший стиль программирования – это сэкономленное время, которое
можно потратить на понимание, модификацию или, как это называют, сопровождение
кода.
Стиль программирования – это архитектура исходного кода – не только его
внешнее оформление, но и использование констант, разбиения кода на функции
или процедуры, способы вызова функций и процедур, согласованность структур,
их потенциал к расширению, гибкость алгоритмов и многое другое. Стиль программирования
сложно отделить от архитектуры самой программы, так как хорошо спроектированная
программа не может иметь плохого стиля программирования.

Конечно же, на ЯВУ легче писать качественно оформленные программы, хотя бы,
потому что ЯВУ уже имеет готовые средства выражения, и шаблоны мышления.

Что такое шаблоны мышления? Всё чем вы так активно пользуетесь:
— типы
— функции
— классы
— массивы
— указатели на типы
— пространства имён
— шаблоны (С++)
Всё это направляет ваше понимание программирования как пространства сотканного
из таких абстракций.

Недавно я прочёл следующую мысль на форуме WASM.RU:

Да, зачем вы пишите программы на asm под Win32, лучше уже писать
под DOS, там хоть нет этого бесконечно однообразного кода создания окон
и обработки сообщений.

Такое заявление говорит, что программист не желает писать проекты более чем
на 6 000 строк (или 3 000 :smile3:). Вместо того чтобы извлечь великую выгоду из
единообразия кода,
мы ругаем его. А ведь это первый звонок к автоматизации программирования.

Неужели программирование asm может быть похоже на Delphi (ох
как его не любят некоторые)? Снова интегрированная среда? Конечно!!! (Жаль,
её всё-таки нет!) Но это не значит, что она играет отрицательную роль.
Хотя о средствах автоматизации и их создании мы поговорим в другой работе.

Ассемблер не определяет шаблонов мышления, и практически не имеет средств
выражения каких либо шаблонов (из-за чего автор пользуется им).

Очень сложно назвать директиву proc средством выражение процедурной
модели программирования.

Однако я могу ручаться, если вы научитесь писать качественно стилизированные
программы на ассемблере, то на ЯВУ… :smile3:.

Об искусстве стилизации или проектировании архитектуры написано слишком мало,
а рассказать хотелось бы слишком много. Только нельзя объять необъятное, и
потому цель этого руководства рассказать об использовании макросов в MASM32,
а также
о том, как их можно либо нужно использовать, чтобы более качественно стилизировать
код.

I.1 Для тех, кто впервые…

Если вы ещё не работали с макросами, или работали, но очень мало, я спешу
признаться, что это руководство не предназначалось для начинающих. Но благодаря
рекомендациям и советам TheSvin/HI-TECH я решился добавить в него вырезки
и упражнения, которые позволят вам быстро войти во вкус макромира MASM32.
Если же вы уже
имеете дело
с макросами, тогда это руководство укрепит ваши знания и представления по
данной теме.

Для исследования макромира MASM мы воспользуемся директивой echo, которая
позволит вывести нам на экран то, что творится в препроцессоре MASM. Очень
удобно, а главное
наглядно. Я уверен, что вы быстро усвоите этот материал.

I.2. Примечания (обо всём понемногу)

В данной работе я часто пишу: «Препроцессор ML». Кто-то из умников (или просто
жаждущих подловить «на горячем») воскликнет: «Да какой же такой ML.EXE – препроцессор?
Наглая ложь». На всякий случай оговорю, что здесь имеется ввиду не утверждение
«ML – препроцессор», а именование его подсистемы – препроцессор.

Всё, что есть в этом руководстве не взято с потолка, и не является вымышленным.
Весь код проверен, и работает именно так как описано, если только автор случайно
не ошибся, что так же случается.

Многое из того, что написано в этом руководстве недокументированно (или плохо
документировано) в официальном. Поэтому вы всегда должны помнить, что если
в следующих версиях ML (например, 8.0) что-то не будет работать, никто не
виноват.

Если вы думаете, что я дизассемблировал ML.EXE – то ошибаетесь. Алгоритмы
работы, приведённые здесь, получены логическим путём на основе знаний работы
компиляторов,
а поэтому их не следует воспринимать как истинные. Важна сама логика работы,
понимание которой, поможет вам безболезненно использовать макро, допуская
меньшее количество ошибок.

На самом деле MASM очень плохо документирован, и видно MS совсем не относится
к нему как к продукту (что вполне очевидно). Хотя уже в MSDN
2002
был
внесён раздел MASM Reference, и всё равно – вы не найдёте лучше описания
чем в
MASM32 by Hutch.

Когда вы прочтете, то воскликните: «Да, зачем мне такой ML?». Есть NASM и FASM – главная надежда мира ассемблерщиков. Однако и теперь ML всё
ещё выигрывает
у них по удобству эксплуатации, большей частью видимо благодаря Хатчу,
и многим
замечательным людям, поддерживающим MASM32. Кто знает, может после
этой статьи кто-то воскликнет: «Я знаю, какой должен быть компилятор
мечты асмовцев!
». И напишет новый компилятор. (Автор шутит ?)

Уверен, что программисты из MS вряд ли прочтут эту статью (они плохо
знакомы с русским), и оно к лучшему. Возможно, такая статья могла
бы их огорчить,
а я не люблю портить настроение людям, трудами которых пользуюсь.
(Снова шутит,
только
про что?)

И наконец-то мне в свою очередь хочется порадоваться, что многие
вопросы по макросам в MASM закрыты на долгое время, во всяком случае,
для русскоязычной
аудитории.
(Шутит, или нет? Гм…)

I.3. Особенности терминологии

Терминология этой статьи различается от терминологии принятой в MASM.

В частности автором было предложено называть:

MacroConstant    EQU  123          ;; Числовая макроконстанта
MacroVar = 123 ;; Числовая макропеременная
MacroText EQU <string> ;; строковая макропеременная
MacroText TEXTEQU <string> ;; строковая макропеременная

В MASM:

MacroConstant    EQU  123           ;; numeric equates
MacroVar = 123 ;; numeric equates
MacroText EQU <string> ;; text macro
MacroText TEXTEQU <string> ;; text macro

Можно было бы попросту выбрать терминологию MASM, однако последняя не позволяет
объяснять материал систематически. То есть все четыре вида выражений – по сути,
являются переменными или константами. Однако в терминологии MASM два последних
определения называются текстовыми макро, подчёркивая их связь с макросами.

Если пойти этим путём, то тогда и первые два определения – являются упрощёнными
определениями макро. Если разработчики желали подчеркнуть, что сама суть
внутренней реализации
ML представляет текстовые макросы как макро, то тогда не ясны те все эффекты
функциональности, обсуждаемые в этой статье.

Что имеет ввиду автор?
Посмотрите что такое макроопределение – это некий текст, который как бы
«вставляется» препроцессором в исходный текст программы в месте вызова
макро.
А что такое в терминологии MASM numeric equates, или text macro – это некоторые
переменные, значения которых «подставляются» в исходный текст программы
во время компиляции вместо имён этих переменных.
Таким образом, можно сказать, что определения представленные выше – макро,
но в упрощённом их виде.

Этот спор не решаем, что не так и важно. Поэтому автор отдаёт предпочтение
двум терминам для «text macro»: «текстовой макро» и «строковая макропеременная».

Понятие: «numeric equates» является общим для первых двух случаев, и разрывает
смысловую связь с двумя последними определениями. Поэтому я пользуюсь своим
вариантом терминологии, который подчёркивает, что определения:

MacroConstant    EQU  123       ;; Числовая макроконстанта
MacroVar = 123 ;; Числовая макропеременная

являются подобными макро. А, кроме того, первое из низ – константа, а второе
– переменная.

I.4. Благодарности

Не могу не написать этот пункт, ибо не только автору обязана эта статья.

Она обязана замечательной версии Win98 с инсталляцией от 2000, которая отформатировала
весь мой винчестер, и унесла в небытие первый вариант настоящей статьи. :smile3:

Не малая заслуга в вопросе терминологии MASM, и его разрешении принадлежит
Four-F, который как он сам мне признался, съел на макросах
собаку, при чём без соли :smile3:.

Когда я думаю, чтобы было бы без самого Маниакального редактора в Inet,
CyberManiacа, то понимаю: без его правок мои статьи приводили
бы в ужас, и лишали разума
всех морально неустойчивых читателей. CyberManiac: «Только такой замечательный
безумец
как ты может выдержать ЭТО!!!» :smile3:.

FatMoon, Rustam, The Svin – вы дали понять мне то, что такая статья действительно
нужна, и это, наверное, самое главное. Вряд ли я бы так долго работал
над ней, если бы меня никто не подталкивал.

Всех кого я забыл поблагодарить здесь, и кого не забыл, жду в условном
месте в условное время для раздачи благодарностей.

С уважением, Edmond/HI-TECH

II. Лень – двигатель Макро

Когда говорят, что лень – это двигатель прогресса, видимо лицемерят или преувеличивают.
Скорее это нежелание выполнять одну и ту же работу очень часто. Первая парадигма
к созданию макро звучит так:

Если есть что-то похожее, что нужно делать очень часто, я могу оформить
это как макроопределение.

Ассемблер, дающий программисту полную свободу в использовании методик программирования,
совершенно лишает его средств для выражения этих методик. Например, ООП. В
MASM32 нет классов, конструкторов и других механизмов, поддерживающих эту абстракцию.
Зато вместо ООП Вы можете придумать множество других методик и абстракций (как,
например модель серверов).

Та или иная методика программирования обязательно состоит из каких-либо компонентов,
которые являются подобными друг другу. Например, следующие макро очень любимы
в примерах пакета MASM32:

  m2m MACRO M1, M2
        push M2
        pop  M1
      ENDM

      return MACRO arg
        mov eax, arg
        ret
      ENDM

Предположим, что кому-то так надоело писать:

        push переменная2
pop переменная1

И он решил придумать макро для этого. Эта пара команд осуществляет пересылку
данных из одной ячейки памяти в другую. То есть теперь в программе, когда вы
захотите написать push/pop, вы можете заменить это некой m2m операнд1,
операнд2
.
Посмотрите на эти два участка кода:

mov wc.cbWndExtra,     NULL
m2m wc.hInstance, hInst
mov wc.hbrBackground, COLOR_BTNFACE+1
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
mov wc.cbWndExtra, NULL
push hInst
pop wc.hInstance,
mov wc.hbrBackground, COLOR_BTNFACE+1

Первый вариант не только занимает меньше строк (что тоже важно), но и намного
понятнее, чем push/pop (если вы, знаете что такое m2m). Конечно, если говорить
о макро m2m, то он имеет и очень важный недостаток.

Мощь макро была бы сказочной, если бы MASM умел следить за
кодом, или ему можно было бы указать, что, например, сейчас регистр ebx
== 0, или eax никем не используется. Хотя мы попробуем достичь подобного
эффекта самостоятельно.

Этот недостаток потеря контроля над оптимальностью кода. Например, более быстрыми,
по сравнению с парой команд push/pop, являются mov eax,… Употребляя макро m2m,
вы получаете худший код, если стремитесь оптимизировать по скорости. И здесь
есть две стороны проектирования кода:

  1. Эффективность кода
  2. Совершенство стилистики

Используя макро m2m, вы повышаете уровень стилистики, так как сокращаете
время на понимание исходного кода (вами же или другим программистом). Однако
с другой
стороны вы теряете эффективность.

Это одна из вечных задач архитектора – найти баланс между эффективностью
в коде и совершенством стилистики.

Другая парадигма использования макро звучит так:

Если, объединяя что-то в одно целое, я улучшаю стиль кода – это можно
сделать в виде макроопределения.

Эта парадигма отличается от предыдущей тем, что создание макроопределения
обуславливается только улучшением стилизации кода, и не имеет особой практической
ценности. Например, я объявил такие макро для определения кода начала и конца
в главном модуле программы:

$$$WIN32START		macro
PUBLIC l$_ExitProgram
_start:
xor ebx,ebx
endm

$$$WIN32END

macro
l$_ExitProgram:
push $$$__null
call ExitProcess
end _startendm

В этих макро нет по сути никакой пользы, кроме эстетической. Зато, глядя на
код, можно сразу понять, что это не что иное, как начало программы нечто вроде
main() в C++.

И последняя парадигма использования макро:

Если ты используешь технологию программирования – попытайся заключить
её в комплекс макроопределений.

Например, для модульного программирования нужно создать макросы для
определения модуля, его частей, кода и данных.

Наиболее важная часть использования макро. Посмотрите, например, файл Objects.INC из пакета MASM32 в папке oop (NaN & Thomas).
Мы начнём создание первых макро со следующей задачи.

Наверное, вы знаете, что EXE приложения всегда могут загружаться по адресу
равному:

PROGRAM_IMAGE_BASE	EQU	400000h

Во-первых, это даёт нам право убрать из приложения всю Relock секцию, тем
самым, уменьшив объём образа (если эта секция нужна для систем плагинов, её
можно держать отдельно).

Во-вторых мы можем более не вызывать функцию GetModuleHandle, что так же
полезно для нас. Использование константы PROGRAM_IMAGE_BASE очень удобно.
Однако, что
будет значить это удобство, если всё-таки PROGRAM_IMAGE_BASE не определено?
Это будет означать, что мы обязаны переписать весь код. А если этого кода
много?

Определённо об этом нужно позаботится заранее. Давайте же будем решать эту
проблему при помощи макро! Для этого нам станут необходимыми некоторые знания
о том, как
обрабатывается макро, и что это такое.

III. Макромир MASM

Макрос представляет собой именованный участок исходного текста программы,
который обрабатывается компилятором каждый раз в том месте, где вызывается
макрос.

Пример:
Создайте небольшой модуль с именем macro.asm.
И напишите в нём несколько строчек

                            .386
                            .data
                            .code
echo Hello!!!
echo Ты должен увидеть во время компиляции

end

Так действует директива echo. С помощью неё можно подсмотреть значения
переменных.

Mycount = 1
%echo @CatStr(%Mycount)

Если вы не знаете, как это работает, не волнуйтесь, обо всём будет рассказано.
А пока несколько экспериментов:

Напишите:

MyMacro		macro reg

              dec    reg     
		endm

		.code

              mov eax,5
MyMacro eax
MyMacro ebx

Взгляните на код программы под отладчиком. Что у вас получилось? Что
будет, если вы измените текст внутри макроопределения?

Теперь напишите:

MyVar = 1

MyMacro		macro

MyVar = MyVar+1
%echo MyVar = @CatStr(%MyVar)

		endm

MyMacro
MyMacro
MyMacro
MyMacro

Каким будет вывод на экран во время компиляции?

С этого момента вам придётся различать в ассемблере ML две подсистемы: препроцессор
и компилятор. Если компилятор переводит код мнемоник в машинный код, вычисляет
значения меток и смещений, то препроцессор занимается вычислением выражений
этапа компиляции, и что самое важное – процессом раскрытия макросов.

Подобно многим объектам мира программирования макро имеет два состояния в
исходном тексте: определение, и использование.

Таким образом, мы будем иметь дело с определением макроса (макроопределением),
и его вызовом (использованием макроса).
Макроопределением называется любой текст, заключённый между ключевыми словами:

MacroName		macro paramlist
макроопределение
endm

При каждом вызове макро, а именно:


MacroName
или
mov eax, MacroName()

Будет анализироваться и исполнятся текст, заключённый в макро. Именно так
это и реализовано в ML. Поскольку текст в макроопределении не компилируется,
то естественно, вы не увидите сообщений об ошибке, даже если с точки зрения
ассемблера эта ошибка будет в теле макроопределения. Однако ошибка появится
при попытке вызова макроопределения, её могут выдать вам, либо сам препроцессор,
либо компилятор, если текст, сгенерированный препроцессором является неверным
с точки зрения компилятора.

Каждый раз, когда препроцессор встречает макроопределение, он помещает его
имя в специальную таблицу, и копирует его тело к себе в память (это не обязательно
именно так, но вам должна быть понятна суть). Встретив макроопределение, препроцессор
не проверяет, а есть ли макро с таким же именем. Это значит, что макро можно
переопределять.

MyMacro         macro
echo Это макро 1
                endm

MyMacro         macro
echo Это макро 2
                endm

MyMacro

  

Вы можете самостоятельно удалять макроопределения, из памяти препроцессора
используя директиву PURGE:

PURGE macroname

Эта директива удаляет тело макроопределения, однако не удаляет имя макро из
таблицы имён. Таким образом, в данном случае:

MyMacro    macro
	mov     eax,ebx
           endm

PURGE MyMacro


;; После этой директивы, MyMacro эквивалентен:
;; MyMacro macro
;;         endm
;; Определению пустого макро.


MyMacro    ;; Ничего не произойдёт.

Разработчики ML задумывали эту директиву для разрешения конфликтов
между файлами с множеством макросов, однако мне совершенно не ясно как ей можно
воспользоваться.
Если вы хотите получить эффект «удаления» макро, лучше применять следующий
метод:

<Имя макро, который нужно «удалить»> macro
.ERR <Попытка вызова макро, который не существует>
endm

В этом случае при попытке воспользоваться таким макро, компилятор выдаст
ошибку, и вы будете проинформированы о его вызове, что намного лучше неведения.
Поэтому просто запомните: «Не нужно использовать директиву PURGE».

Конечно же, использование макро не было бы столь полезным, если бы макро
не имел формальных параметров. При вызове макро, препроцессор заменяет все
имена
формальных параметров
их непосредственными значениями в теле макроопределения. Список формальных
параметров разделяется запятой, и может иметь вид:

MyMacro macro param0, param1:REQ, param2 := <0>,param3:VARARG

Здесь:
Param0 – пример определения параметра.
Param1:REQ – ключевое слово REQ указывает на то, что этот параметр обязательный.
То есть, если он не будет указан, вы получите ошибку этапа компиляции.
Param2:=<0> – пример параметра, который имеет значение по умолчанию.
То есть если этот параметр не будет указан при вызове макро, он будет равен
этому значению.

Заметьте, что при вызове макро параметр может быть не определён:

      MyMacro param1,,param3

Значение второго параметра неопределенно.

Param3:vararg – становится именем параметра, который воспринимает всё остальное
как строку. При этом запятые между параметрами так же попадают в строку, а
значит число параметров макроса в принципе неограниченно.

Ограничениям являются особенности архитектуры компилятора.
Так, например, компилятор имеет ограничение на длину логической строки,
которая равна 512 байтам.

Конечно же, после параметра с директивой vararg не возможно объявить другие
параметры.

Обратите внимание, что если при определении формального
параметра в макро нет директивы – он считается необязательным параметром.
Более подробно о вызове макро и значении параметров я расскажу далее.

Пример:
Так что же происходит с формальными параметрами?
Посмотрите, как работает препроцессор ML:

       MyMacro     macro param1,param2

              mov    eax, param1
              mov    ebx, param2

                   endm

       MyMacro var, 123
	   

1. Препроцессор берёт текст внутри макро, и заменяет
в нём все
слова param1, param2, на их значения:
«
mov eax, var
mov ebx, 123
»

2. Полученный текст вставляет на место вызова макро, и передаёт компилятору.

Вот интересно, а что будет если:

MyMacro  macro param1,param2


          MyMacro2   macro  param1
              mov    eax, param1
              mov    ebx, param2
                     endm
         
         endm

MyMacro var, 123

Можно различать два вида макро – макропроцедуры и макрофункции.

В официальном руководстве MASM различается четыре основных
вида макро.
Text macros – текстовый макрос
Macro procedures – макро-процедура
Repeat blocks – блок повторения
Macro functions – макро-функция
Однако автор считает, что разделение макро на два вида – лучше систематизирует
материал, и отражает суть темы.

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

         mov     eax,@GetModuleHandle()

Заметьте, что к макрофункции невозможно обратится как к макро, вы всегда должны
заключать формальные параметры макрофункции между «()», иначе MASM не будет
распознавать её как макрофункцию:

         mov     eax,@GetModuleHandle
error A2148: invalid symbol type in expression : @GetModuleHandle

Препроцессор MASM анализирует текст макроопределения на наличие директивы
exitm, и помечает макрос как макрофункцию.

Ключевое слово exitm <retval>, аналогично оператору return в C++, выполнение
макро заканчивается, и возвращается необязательный параметр retval. Этот параметр
– строка, которую должен вернуть макрос.

Если в макро директива EXITM употребляется без параметров:
EXITM
То препроцессор считает, что это макропроцедура, а не макрофункция.
Если в макроопределении есть два вида EXITM с параметром и без, то ML выдаст
ошибку о недопустимом использовании директивы EXITM.
EXITM <>
EXITM
: error A2126: EXITM used inconsistently
Это подчёркивает тот факт, что макрофункцией считается только макро, который
возвращает значение (хотя бы пустое), а директива EXITM без параметров
не возвращает никакого значения, что недопустимо в макрофункции.

Таким образом, окончательно будем считать, что макро, которые не возвращают
значение – это макропроцедуры, а макро, которые возвращают значение
(хотя бы пустую строку) – это макрофункции.


;#######################################################
@GetModuleHandle			macro
Invoke GetModuleHandle,0
					exitm 
					endm
			.code
; Это макрофункция так нельзя
@GetModuleHandle ;;– ошибка
; Так можно
@GetModuleHandle()
;########################################################
@GetModuleHandle			macro
Invoke GetModuleHandle,0
					endm
			.code
; Это макрос. Так правильно
@GetModuleHandle
; Так можно, но всё равно это вызывает ошибку ?
; warning A4006: too many arguments in macro call
@GetModuleHandle()
; Это макро, а не макрофункция так нельзя!!!
		mov	eax,@GetModuleHandle
; И так нельзя
		mov	eax,@GetModuleHandle()
;########################################################  
  

Что касается директивы endm, которая заканчивает каждое макроопределение,
в руководстве написано, что при помощи неё так же можно указать возвращаемый
параметр:
endm <retvalue>
Однако на практике это не так. ? Очень странно, хотя об этом чётко написано
в руководстве.

Заметьте, что макропроцедура может быть вызвана только в начале строки:

@GetModuleHandle
;; Но не так:
mov eax,@MyMacro

Макрофункция может быть вызвана в любых выражениях:

;; Так:
mov eax,@GetModuleHandle()
;; И так:
@FunMacro()
;; И так:
@GetModuleHandle() EQU eax

III.1. Функционирование макросов

Чтобы строить макросы, важно понимать, как они работают, и как их обрабатывает
MASM. Давайте рассмотрим типичный макро, и этапы его обработки.

MyMacro	macro param1,param2,param3:VARARG
echo param1
echo param2
echo param3
		    endm 


MyMacro	Параметр 1, Параметр 2, Параметр 3, Параметр 4
;; Вывод -=-=-=-=-=-=-=-=
Параметр 1
Параметр 2
Параметр 3,Параметр 4

1. Компилятор встречает лексему MyMacro

2. Он проверяет, содержится ли эта лексема в словаре ключевых слов

3. Если нет, то он проверяет, содержится ли эта лексема в списке макросов.

4. Если да, он передаёт текст, содержащийся в макро препроцессору. Препроцессор
заменяет все вхождения формальных параметров в этом тексте на их значения.
В данном случае мы имеем:

echo Параметр 1
echo Параметр 2
echo Параметр 3,Параметр 4

5. Препроцессор возвращает компилятору обработанный текст, который после компилируется.

Обратите внимание на пункт 4 и 5. Они ключевые. Очень часто при работе с макроопределениями
появляются ошибки из-за неверного понимания порядка генерирования макро текста.
Например:

PROGRAM_IMAGE_BASE	EQU	400000h
FunMacro	macro
		exitm <Параметр 3,параметр 4>
		    endm

MyMacro	macro param1,param2,param3:VARARG
echo param1
echo param2
echo param3
		    endm 

MyMacro	PROGRAM_IMAGE_BASE, FunMacro(),Параметр 5

А теперь самостоятельно опишите порядок действий компилятора при вызове этого
макро. Запишите его себе куда-нибудь, так чтобы сравнить, и смотрите на вывод:

PROGRAM_IMAGE_BASE
Параметр 3, Параметр 4
Параметр 5

Прежде чем объяснять действительный порядок, я оговорюсь, что директива echoникогда не обрабатывает определённые константы, такие как PROGRAM_IMAGE_BASE.

Это утверждение справедливо даже тогда, когда перед директивой echo стоит
оператор %, который может раскрывать только текстовые макроопределения.
То есть выражение:

echo FunMacro()

Даст результат:

FunMacro()

Теперь, когда мы немного порассуждали можно привести тот текст, который генерируется
из макро:

echo PROGRAM_IMAGE_BASE
echo Параметр 3, Параметр 4
echo Параметр 5

Это означает следующее:

  1. При вызове макро, значение формальных параметров воспринимается как
    текст, и передаётся в макро как строка.
  2. Исключение составляют лишь макрофункции, результат выполнения которых
    вычисляется и присваивается значению параметра.

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

MyMacro	%PROGRAM_IMAGE_BASE, FunMacro,Параметр 5

То получим вывод:

4194304			;; Значение PROGRAM_IMAGE_BASE
Параметр 3, Параметр 4
Параметр 5

Давайте рассмотрим ещё один пример, который хорошо показывает, как работает
макро. Например, вы определили макропроцедуру (именно его, а не макрофункцию).
То когда вы пишите такое:

@Macro что-то, что придёт вам в голову [символ возврата каретки]

Что делает препроцессор ML:

1. Считывает всю строку до символа возврата каретки;

2. Смотрит, как вы определили параметры в макро;

3. Сканирует строку на наличие символа «,» или «<», «>»;

Вам может показаться странным, но препроцессору всё равно,
какие символы идут во время вызова макро. То есть вы можете вызвать макро
так:

@MyMacro Привет, это кириллица в файле,
 и ML не будет на неё ругаться
или
@MyMacro `!@#$%^&*(){}[]

Посмотрите как СИльно (от буквы )
будет выглядеть макро в MASM:

MyMacro{Это что С++?}
MyMacro[Нет, это MASM]

4. Назначает формальным параметрам (любого типа, кроме VARARG) макро участки
строк, которые были определены разделителями запятыми (предварительно очистив
от хвостовых и начальных пробелов, если только строка не была определена в
угловых кавычках <>);

5. Если макро содержит формальный параметр типа VARARG, то ML сперва
инициализирует значениями (согласно пункту 4) обычные формальные параметры,
и только потом
назначает параметру типа VARARG (который может быть только один в
конце списка параметров) всю строку до конца.

Если вы пишите макровызов как
@Macro Param1 , Param2
То значение параметров будут:
param1 = «Param1»
param2 = «Param2»
Если вы хотите передать сами значения строк, то должны заключит их в угловые
кавычки:
@Macro < Param1 >,< Param2 >

6. Препроцессор разрешает все вызовы макрофункций, если они есть в лексемах
параметра, и присваивает их результат соответствующему параметру. Если лексему
в строке параметра предваряет символ %, то он вычисляет её значение до того,
как передаст строку внутрь макро.

Благодаря именно такому порядку:
1. Разделение строки на макропараметры
2. Поиск и Вызов макрофункций в значениях макропараметров
3. Присвоение результатов соответствующему макропараметру

в следующем случае:

MyMacro  macro param1,param2,param3
echo param1
         endm
 
--------------------------------------
FunMacro     macro param:VARARG
		exitm param
             endm


MyMacro FunMacro(param1, param2, param3)


OUT:
param1, param2, param3
--------------------------------------		
		

строка, возращаемая макрофункцией присваивается параметру param1, а не
param2, param3

Теперь вы в состоянии объяснить следующую ситуацию:

MyMacro    macroendm


MyMacro()


Предупреждение при компиляции:
: warning A4006: too many arguments in macro call
  

Как нужно было бы изменить этот макро (именно макро, а не макрофункцию), чтобы
предупреждение не выдавалось? А почему оно происходит?

Если вы с лёгкостью ответили на этот вопрос, значит, материал усвоен, иначе
советую ещё раз прочитать его, и ответить на следующий вопрос.

Как должен понять компилятор следующий код:

MyMacro     macro param1
param1
            endm 

MyMacro = 2  
  

Естественно отвечать на этот вопрос вы должны без помощи компилятора (то есть
проверить компиляцией). Если вы не можете ответить на этот вопрос, или неуверенны
в верности ответа, я поменяю задание:

MyMacro     macro param1
echo param1
            endm 

MyMacro = 2  
  

Запустите его в ML. Если и теперь вы сомневаетесь – перечитайте этот пункт
снова и снова, продолжая экспериментировать.

III.2. Определение макро переменных и строк

Я бы назвал следующее:

Param = 0
Constant EQU 123
WASM EQU <One Wonderful Wonderful ASM>
WASM_RU TEXTEQU <http://www.wasm.ru>

макропеременными (с тем фактом, что переменная может иметь константный тип).

В терминологии MASM:

WASM       EQU <One Wonderful Wonderful ASM>
WASM_RU TEXTEQU <http://www.wasm.ru> ;; Такие определения называются текстовыми макро. ;; В этой статье вы встретите два варианта определений

Потому что под термином «переменная» понимается:

var	dd	123

Переменные являются частью программы, а макропеременные живут только на
этапе компиляции. По сути, они есть более простым видом макроопределений, и
поэтому их стоит понимать как специальные макро, которые так же раскрываются
препроцессором.

Макропеременная может иметь только три типа – целочисленная макропеременная
INEGER4 (dword), целочисленная макроконстанта или текстовой макро (строковая
макропеременная).

Автор считает значительным упущением отсутствия возможности
определять тип макропеременной. Это очень сильно ограничивает возможности
макропрепроцессора. Но что поделать.

При чём, в зависимости от вида определения макропеременной ML считает, что:

Param = 0          ;; Param – это целочисленная макропеременная
Constant   EQU 123 ;; Макроконстанта
;; Текстовой макро (Макропеременная строкового типа)
;; (Это не так в руководстве MASM)
Var EQU qwer
;; Текстовой макро (Макропеременная строкового типа)
WASM EQU <One Wonderful Wonderful ASM>
;; Текстовой макро (Макропеременная строкового типа)
WASM_RU TEXTEQU <http://www.wasm.ru>

Как вы уже догадались, каждое макроопределение обладает своими свойствами
и возможностями.

  1. Целочисленная макропеременная. Имеет тип INT (dword). Может участвовать
    во всех арифметических выражениях MASM. Как переменная она может изменять
    своё значение.
  2. Макроконстанта может иметь целочисленное значение. Её значение не может
    быть повторно изменено.
  3. Текстовой макро может быть любой строкой не более 255 символов. Поскольку
    он имеет статус переменной, его значение может быть изменено.

А теперь подробнее. Если с целочисленными макропеременными в достаточной степени
ясно. То с определениями EQU полный бардак.

Как и в случае с вызовами макро, автор попытается построить алгоритм анализа
EQU выражений:

1. Анализируем правую часть. В анализе правой части препроцессор выделяет
лексемы, которые классифицирует как числа, строки. Так, например, в выражении:

qqqq	EQU 1234567890 string1 23456789012390 macrofun()

«1234567890» – это лексема число, а «string1» – это строка, «macrofun()» –
это всё равно строка (а не макрофункция!!!).

Именно по этому такое определение будет давать ошибку:
qqqq EQU 156n7
: error A2048: nondigit in number

2. Если правая часть является верным определением числа в MASM, то есть 123
или 123h или 0101b – выполнить шаг три, иначе шаг четыре.

Обратите внимание, что числа с плавающей запятой в этом случае
считаются строкой.

Такое поведение связано с внутренней организацией препроцессора ML,
который просто «не понимает» чисел с плавающей запятой, и не умеет
с ними работать.

То есть тип макропеременной Float:

        Float EQU	1.2345 

будет не числовой, а строковой

3. Если полученное число имеет значение, не превышающее диапазон значений
для dword – это целочисленная макроконстанта.

Если правая часть для EQU является верным числом более 25 символов,
выдаётся ошибка:
: error A2071: initializer magnitude too large for specified size

При чём такая ошибка появляется даже в том случае, если выражение содержит
другие символы через пробел:

qqqq	EQU 1234567890123456789012390 dfdg

Это объясняется действиями в пункте 1, когда ML анализирует лексемы.
Кроме того, если числовая лексема не соответствует правилам определения
чисел в ML, то есть в середине числа появляется символ A-Z, либо другие
символы, не входящие в разряд разделителей – то такая лексема порождает
ошибку, даже если она содержит число большее dword диапазона.

4. Иначе – это строковая макропеременная.

Теперь попробуйте самостоятельно определить тип макроопределения:

qqqq	EQU 0x123234
qqqq EQU 123234h
qqqq EQU 012323
qqqq EQU 0.123234
qqqq EQU 123234 342
qqqq EQU 4294967296

В данном примере только второй и третий вариант – макроконстанта, остальные
– текстовые макро. Последний вариант таким не является, так как превышает диапазон
значений для dword.

Замете, что поскольку препроцессор в правой части выделяет корректные выражения,
правая часть не может состоять из недопустимых символов. Но при этом она может
состоять из директивы определения литерала: «<>» – угловых кавычек.

Директива <текст> – определяет литерал, таким образом, указывая препроцессору
ML, что он должен воспринимать нечто как строку символов. При этом сами «<>»
– в строку не попадают. Директива <> – является единственной директивой
для препроцессора ML, которая определяет литералы.

    Именно по этой причине, все виды кавычек – двойные, одинарные,
` – вот такие одинарные, воспринимаются как простые символы, и как следствие
проходят к значениям параметров макро. То есть, например:
MyMacro “Привет, это строка в двойных кавычках”
MyMacro ‘Привет, это строка в одинарных кавычках’
MyMacro `Привет, это строка в специальных кавычках`
MyMacro «Привет, это строка»‘И это’

    И замете, что во всех случаях кавычки так же попадают в значения формального
параметра макро. Вы можете использовать этот факт, например, для того,
чтобы менять поведение макро, в зависимости от типа кавычек обрамляющих
строку.

Кроме директивы, определяющей литерал, препроцессор ML имеет свой ESC-символ
(символ отмены). В отличие от С этот символ – «!». Он отменяет
действие других символов (<, >, «, ‘, %, ; , а так же символ запятой),
которые могут иметь функциональность в том, или ином выражении. Если вы хотите
получить «!»,
вы должны использовать последовательность «!!».

К сожалению, не обходится без проблем и с символом отмены «!». Восстановить
точный алгоритм работы мне не удалось. Единственное, что возможно – это
привести несколько
примеров с непонятными эффектами при его использовании:

literal    EQU	<!>      ;; Пустая строка
;; Ошибка – ;;: error A2045: missing angle bracket or brace in literal
literal EQU <!!>
;; Один символ «!»
literal EQU <!!!!>
;; Не имеют эффекта
literal EQU <Привет!" fgd!">
literal EQU <Привет" fgd">
;; Один символ «>»
literal EQU <!!!>> ;; literal = «>»
literal EQU <Текст!!!>> ;; literal = «Текст>»
;; Хотя при вызове макро, «!» ведёт себя нормально
;; а так же он ведёт себя нормально в директиве TEXTEQU
Char <Текст!>>

Вывод – не пользуйтесь директивой EQU для определения литералов, для этого
есть другая директива – TEXTEQU.

Для директивы TEXTEQU алгоритм несколько отличен от алгоритма EQU, так как
в TEXTEQU обрабатывается правое выражение на наличие символа %. То есть
вы можете
определить этот код:

literal	TEXTEQU	%FunMacro()

Или

literal	TEXTEQU	%(10-5)*30		;; literal = “150”

На самом деле как вы видите, внутренняя работа TEXTEQU значительно отличается
от EQU <>. Видимо по этому разработчики ML решили её ввести.

В руководстве MASM32 написано:
———————————————————————————————
The TEXTEQU directive acts like the EQU directive with text equates but
performs macro substitution at assembly and does not require angle brackets.
The TEXTEQU directive will also resolve the value of an expression preceded
by a percent sign (%). The EQU directive does not perform macro substitution
or expression evaluation for strings.
———————————————————————————————

Теперь вы должны понимать, что это не совсем так. Является ли это ошибкой
разработчиков ML? Видимо да. В частности EQU не должна была переводить
в статус переменных литералов определения типа:

       NOLITERAL EQU db

И конструкция ниже должна была бы вызывать ошибку:

       literal	EQU	db
       literal	EQU	dw

Но ошибка не появляется, более того значение literal меняется на dw

В заключении к этому пункту, вы должны осознать, что тип определений невозможно
изменить. То есть переменная не может стать целочисленной константой:

literal    EQU	string
literal EQU 123 ;; Это текстовой макро

Второе переопределение символа literal, не изменит его тип на тип целочисленной
константы.

Думаю, у Вас возник вопрос:
– Что такое? Недокументированные возможности MASM?

У меня есть веские основания считать это ничем иным, как
ошибкой разработчиков. Давайте предположим, что все макропеременные хранятся
компилятором в памяти в виде массива структур. Не вдаваясь в подробности,
пусть эта
структура будет такая:

macrodefine	struct
   type	dd	?	;; тип макроконстанты
   value	dd	?
   ends

Как видно из структуры, значение макроконстанты может быть только dword’ом.
Если это строка, то в поле value может быть записан указатель на строку
(например, ASCIIZ).

Поле type может принимать только два значения, которое описывает тип
value: либо value – содержит числовое значение макропеременной (константы).

Если определяется числовая константа то, вызывается одна функция (назовём
её setmacrodefine_val()), которая добавляет в таблицу макроконстанту.

Это конечно предположение. И в действительности всё может быть ещё
проще или ещё сложнее. Однако вероятность того, что свойства макропеременных
хранятся именно подобным образом близка к единице. Теперь если
вы немного подумаете, то поймёте:

string    EQU <string>       ;; Строковая макропеременная
string    TEXTEQU string     ;; Строковая макропеременная
string    EQU string         ;; Должна была быть константой

Последний случай записывается в таблицу, как строковая макропеременная
по той простой причине, что string не может быть записано в поле value,
а поле type не имеет специального значения, чтобы указать, что value – это константный указатель на строку (помните C++?).

В конце концов, совершенно не важно угадал ли автор причину,
или нет. Важно другое – что ошибка достаточно явная. А, кроме того, так
и
не была исправлена
до сих пор (версия 7.0). Зато теперь вы сможет с пониманием отнестись к таким
неожиданным эффектам.

Видимо разработчики не задумываются о том, что кто-то будет использовать
определения MASM, иначе, нежели это написано в руководстве. И кому-то взбредёт
в голову
проверить, а можно ли переопределить EQU.

А подумайте, к каким бы серьёзным неуловимым ошибкам произвела бы эта
халатность, если бы на MASM писали сложные приложения. Но как видно
их никто не пишет.

Свои особенности имеют так же целочисленные выражения с оператором «=». В
таких выражениях перед их выполнением осуществляется полная замена всех макроконстант,
макропеременных на их значения, и вызов всех макрофункций.

Как вы думаете, что будет в следующем примере:

literal	EQU	Something
literal = 1234

Варианты ответа:

  1. Произойдёт ошибка переопределения константы.
  2. literal = 1234.

Второй вариант ответа мы должны откинуть сразу, потому что в этом пункте
чётко определили, что данное переопределение невозможно. Первый вариант
ответа больше
похож на правду.… Однако не соответствует истине. Что же произошло? А
произошло следующее:

  1. Препроцессор нашёл лексемы «literal» и «1234».
  2. Обнаружил, что «literal» является текстовым макро, и именно поэтому
    выполнил замену лексемы «literal» на её строковое значение.
  3. Проанализировал строку: «Something = 1234».

Этот факт может быть легко доказан, следующим тестом:

literal	EQU	Something
literal 	= 1234

%echo @CatStr(%Something)
============================
Вывод:
1234

Если вас сбил с толку этот пример, не отчаивайтесь. Всё дело в том, что препроцессор
ML в разных выражениях по-разному заменяет макропеременные. Вот об этом мы
и поговорим в следующем пункте.

А пока подумайте, что должно случится в этом примере:

num		EQU number
num EQU 123
num = 1234

На этом можно было бы закончить данный пункт, если бы не одна особенность
использования строк в вызове макро. А точнее приоритет анализа кавычек и директивы
определения литерала <>. Не смотря на описанный выше алгоритм поведения
макро, оказывается, что препроцессор при вызове макро выполняет определение
литерала в кавычках, но что самое интересное, как было отмечено, выше сами
кавычки попадают в строку. Если вам нужно передать макро одиночную кавычку
вы должны воспользоваться символом отмены «!». Однако самое неприятное таится
в том, что символы «<>» и кавычки конкурируют между собой в определениях
строк. Например, попробуйте сказать, что должно было бы получиться в этом случае:

%echo @CatStr(<Раз">,<"Два>)
OUT:
Раз">,<"Два

А можно было бы подумать, что ML должен принять операторы <> и запятую.
Данное место – источник многих сложно обнаруживаемых ошибок. Например:

FORC char,<str>
m$__charcode = @InStr (1,<@ABCDEFGHIJKLMNOPQRSTUVWXYZ>,<char>)

Если в строке попадается символ кавычки, а макропеременная char заменяется
на значение кавычки, имеем:

m$__charcode = @InStr (1,<@ABCDEFGHIJKLMNOPQRSTUVWXYZ>,<”>)

В этом случае мы получаем ошибку:

missing single or double quotation mark in string

Так и должно быть, потому что кавычки имеют высший приоритет анализа, чем
оператор <>. Более того, угловые кавычки <> имеют самый низкий
приоритет по отношению ко всем спец. символам, что согласуется с MASM Reference.
Посмотрите на Дополнение к статье: пункт 3.a.i, который подозрительно выделен
«жирным». В частности, следующее выражение, которое работает без проблем:

TEXT   TEXTEQU <">	;; Это работает?
TEXT TEXTEQU <;> ;; И это???

Появляется закономерный вопрос: для чего символ отмены «!»?
Данный пример демонстрирует скрытые глубины анализатора ML. А точнее его архитектурное
несовершенство. Так как выражения с TEXTEQU как видно обрабатываются отдельной
функцией, которая проверяет в первую очередь наличие угловых скобок «<>».
Все другие выражения ML обрабатываются другой стандартной функцией, которая
была написана задолго до появления TEXTEQU.

Замечательная наука всем программистам, которая демонстрирует,
во что выливается халатность архитектора при дальнейших попытках расширения
продукта.

Зато благодаря TEXTEQU пример с поиском символа в строке имеет решение:

m$__char TEXTEQU <char>
m$__charcode = @InStr (1,<@ABCDEFGHIJKLMNOPQRSTUVWXYZ>,%m$__char)

Единственно, отчего не может помочь данный код – это от вылавливания в строке
символов «> или <». Для этого можно использовать специальную проверку
в условных блоках на наличие символа «>», но при этом придётся отказаться
от микроблока FORC.

III.3. Обработка выражения в MASM

MASM обрабатывает выражения в правой и левой части в зависимости от контекста.
Там, где вам необходима предварительная обработка выражений, используется оператор
«%». Он заставляет препроцессор ML сначала вычислить выражение
после оператора
% (то есть выражение в правой части относительно %), и только
потом продолжить анализ всей строки. Например, если вы хотите, чтобы при вызове
макро:

num		TEXTEQU	<123>
FunMacro num

макропараметр был бы равен не строке «num», а значению текстового макро num,
вы должны поставить оператор % перед num. Например:

FunMacro %num
;;или
FunMacro %(1+2*num)

Но и с оператором % не всё гладко.
Оказывается препроцессор ML, различает два (фактически три) вида выражений, в
которых используется оператор %. Первый вид выражений – Арифметические:

Все выражения, содержащие операторы +,-,*, а так же сдвиговые и битовые
операции

Строковые выражения:

Все выражения результат вычисления которых – строка.

Примеры:

;Арифметические выражения
%(num shl 3)
%num = 2134 shl 3 + 2*6
;Всё равно арифметическое выражение
%(num shl 3 @CatStr(num))
;Строковое выражение
%(@CatStr(num shl 3))
;Строковое выражение
%PROGRAM IMAGE

Так вот что интересно.

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

То есть:

Левая часть = Правая часть
(Вызвать все макрофункции, и заменить все строковые макропеременные) =
(Вызвать все макрофункции, и заменить все строковые и целочисленные макропеременные
и константы)

В строковых выражениях происходит замена только строковых макропеременных
(текстовых макро) (замете, что в ML нет строковых макроконстант). Это значит
что в случае:

%echo PROGRAM_IMAGE_BASE

Появится: «PROGRAM_IMAGE_BASE», а не его числовое значение.

Однако есть и третий частный случай, когда оператор % относится только к
одному литералу:

%literal

В этом случае происходит полный комплекс подстановок:

  1. Вызываются макрофункции.
  2. Заменяются все макропеременные или макроконстанты.

Например:

FunMacro %literal

Значение literal будет подставлено в вызов макро, в независимости от того,
какой тип имеет literal.

Выдержка их руководства MASM:
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
temp TEXTEQU %(SIZEOF array / LENGTHOF array)
% ECHO Bytes per element: temp

Note that you cannot get the same results simply by putting the % at
the beginning of the first echo line, because % expands only text macros,
not numeric equates or constant expressions.
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

Следует так же отметить, что в выражениях с exitm оператор % работает
точно
так же, как с выражениями в TEXTEQU.

III.4. Целочисленные выражения MASM

Целочисленные, побитовые операции так же необходимы разработчику макроопределений.
Они дают возможность скрыть обработку битовых полей, или вычисление сложных
выражений. Например, как это сделано в макрофункции $$$MAKELANGID.

$$$MAKELANGID		macro p:REQ,s:REQ
m$__langid = (s SHL 10) or p
EXITM <m$__langid>
endm

Вы всегда должны помнить, что препроцессор MASM не различается знаковые и
беззнаковые числа (подобно тому, как это делает x86), и значение числа
не может выходить
за диапазон dword. Препроцессор MASM не выдаёт предупреждений при переполнении.
Следующий пример демонстрирует такое поведение:

myint = 0ffffffffh
myint = myint + 1	;; myint = 0
%echo @CatStr(%myint)

=================================

OUT:
0

;; Ещё один пример с умножением:

myint = 0ffffffffh
;; 
;; 0ffffffffh * 2 = (dword)1FFFFFFFEh = 4294967294
myint = myint * 2
%echo @CatStr(%myint)
=================================
OUT:
4294967294

В следующей статье мы поговорим про то, как работать с 64-bits макропеременными,
используя данный факт.

Ниже приводится список операций, которые могут участвовать в целочисленных
выражениях MASM.

Оператор Пример Описание
AND res = op1 AND op2 Операция логического «И» над каждым битом операндов op1 и op2.
OR res = op1 OR op2 Операция логического «ИЛИ» над каждым битом операндов op1, op2
NOT res = NOT op1 Операция логического «НЕ» над каждым битом операнда op1
XOR res = op1 XOR op2 Операция XOR между операндами op1, op2
SHL res  = op1 SHL count Выполняет побитовый сдвиг влево (наподобие команды x86 shl) операнда
op1, на количество бит, указанное в операнде count.
SHR res  = op1 SHL count Выполняет побитовый сдвиг вправо операнда op1, на число бит, указанное
в операнде count.
+,-,*,/   Основные математические операции
MOD res = op1 MOD op2 Возвращает остаток от деления операнда op1 на операнд op2
[] res = op1[op2] Операция: «Смещение». Выполняет сложение операндов op1 и op2

III.5. Вычисление рекурсивных выражений

Теперь, когда мы рассмотрели правила анализа и вычисления выражений в MASM,
остаётся раскрыть важный вопрос: «Как происходит анализ выражений, если
они
состоят из других выражений?
».

Обычно это называется короче: вложенные выражения.

Вложенное выражение – это такое выражение, элементы
которого сами являются выражениями, которые так же могут иметь
вложенность.

Замороченное определение, похожее на «Иди туда, не знаю куда,
возьми то, не знаю что» – пример старинной народной русской рекурсии,
которая так часто встречается в нашей жизни. :smile3:)

Например, вызов макрофункции при вызове макро – это вложенное выражение:

MyMacro   FunMacro(Мой парамерт)
;;Или это:
%echo FunMacro(Мой параметр)
;;Или это:
MyMacro   FunMacro(Fun2(Привет))

Вложенность характеризуется параметром количества уровней вложенности. В недавнем
примере уровень вложенности был равен двум. При чём вызов Fun2() можно называть
выражением низшего уровня вложенности, а вызов макро MyMacro – выражением верхнего
уровня.

После анализа выражений, и получения их многоуровневой структуры вложенности,
препроцессор начинает вычислять результат выражения самого низшего уровня.
Потом подставляет его результат в выражение следующего уровня, и так далее.

Например, для случая:

Fun2   macro param
exitm <MyCount = param>
endm
FunMacro(Fun2(%(12+34)))

Порядок вычислений такой:

  1. %(12+34) = 46
  2. Fun2(46)
  3. FunMacro(MyCount = 46)
  4. Результат выполнения FunMacro(MyCount = 46)

А иначе препроцессор не смог бы. Если бы он начал вычисления
выражений с верхнего уровня, то это то же самое, как если бы он попытался
выполнить народную русскую рекурсию:
«Пойди туда, не знаю куда…, вычисли то, не знаю что»
или
FunMacro(???)

То есть: Вложенные выражения вычисляются последовательно от низшего уровня
к верхнему, и результаты вычисления каждого уровня становятся материалом для
выражений следующего уровня.

Это правило называется рекурсивным вычислением выражений. Оно используется
везде, кроме мест вычисления значений макропараметров при вызове макро
(как макросов,
так и макрофункций). В этом случае действует правило: результат вложенного
выражения присваивается макропараметру и не анализируется повторно. Это
значит, что в данном
примере:

myvar	EQU	<123>

MyMacro	macro param1,param2,param3
echo param1
	endm 

FunMacro	macro param:VARARG
		exitm <param>
		endm

MyMacro FunMacro(var,@CatStr(<%>,myvar),var4)

вывод будет таким:

var,myvar,var4

То есть препроцессор не будет снова вычислять выражение для второго макропараметра
функции FunMacro(). Если бы он сделал это, то тогда вывод был бы таким, как
в этом случае:

%echo FunMacro(var,@CatStr(<%>,myvar),var4)
Вывод:
var,123,var4

Теперь, когда вы знаете все тонкости вычисления выражений в MASM, настало
время рассмотреть Встроенные макрофункции и директивы, которые участвуют в
этих выражениях.

III.6. Встроенные макрофункции и директивы

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

MASM обладает несколькими встроенными макрофункциями, макропеременными и
макроконстантами, которые работают так, как если бы они были макро, определённые
вами. Вот список
этих предопределений:

Имя макроопределения, его тип Описание
Определения Даты и Времени
@Date,

текстовое макроопределение (не макрофункция)
Возвращает строку вида MM/ДД/ГГ
Где:
MM – месяц, две цифры
ДД – день, две
цифры
ГГ – год, две цифры
@Time,

текстовое макроопределение (не макрофункция)
Возвращает текущее время в 24-х часовом формате вида ЧЧ:ММ:СС
ЧЧ – часы,
два числа
ММ – минуты, два числа
СС – секунды, два числа
Информация об окружении
@Cpu, числовая макроконстанта Битовая маска, определяющая режим работы процессора. Никакой информации
о полях этой маски нет.
@Environ(env), макрофункция

Возвращает строковое значение переменной среды окружения. Например:

%echo @Environ(TEMP)

Вывод: F:Tempasm

@Interface, целочисленная макроконстанта Информация о языковых параметрах вызова.
@Version,  строковая макроконстанта

Возвращает версию ML.

Например:

%echo Version = @Version
Вывод: Version   = 614Или 615 в MASM 6.15
Информация о файле
@FileCur, строковая макропеременная

Возвращает имя файла и путь к нему (если есть), так как был подан этот
файл в командной строке компилятору ML.

Пример:

%echo FileCur = @FileCur
Вывод: FileCur = .start.asm
@FileName, строковая макропеременная

Возвращает имя файла, без его расширения. То есть для модуля start.asm:

%echo FileName = @FileName
Вывод:FileName = START
@Line, целочисленная макроконстанта

Возвращает номер текущей строки в файле.

Пример:

%echo Line = @CatStr(%@Line)
Вывод:Line = 31

Строковые макрофункции
@CatStr( string1 [[, string2…]] ), макрофункция

Возвращает строку, созданную объединением строк параметров функции.

Пример:

%echo @CatStr(<my>,var)
Вывод:Myvar
@InStr( [[position]], string1, string2 ), макрофункция

Возвращает позицию вхождения строки string2 в строку string1. Если параметр
position определён, тогда поиск начинается именно с этой позиции. Отсчёт
позиции начинается с единицы. В случае, если вхождение не найдено макрофункция
возвращает значение 0. Параметр position должен быть целым числом больше
нуля, но не равным нулю.

Пример:

%echo @InStr(1,asdfg,s)
Вывод:02
@SizeStr( string ) макрофункция Возвращает число, характеризующее длину строки, или, что тоже самое
количество символов в строке. Функция возвращает число, однако, поскольку
это макрофункция то тип возвращаемого значения – строка.
@SubStr( string, position [[, length]] ) макрофункция

Возвращает подстроку строки string, начиная с позиции, указанной в параметре
position (отсчёт начинается с 1). Если необязательный параметр length задан,
он ограничивает размер возвращаемой строки. Параметр length не может быть
меньше нуля, и не может быть строкой.

Пример:

%echo @SubStr(1234567890,2)
%echo @SubStr(1234567890,1,5)


Вывод:
234567890
12345
Информация о сегментах
@code, строковая  макропеременная Возвращает имя сегмента кода.
@data, строковая макропеременная

Возвращает модель памяти.

Пример:

%echo data    = @data
Вывод:data    = FLAT

@fardata?, строковая макропеременная Равен имени сегмента FARDATA?
@WordSize, численная константа Содержит размер слова в байтах.

Для 16-bits – 2.

Для 32-bits – 4.
@CodeSize, численная константа Содержит идентификатор типа памяти.
0 – TINY, SMALL, COMPACT, FLAT.
1
MEDIUM, LARGE, HUGE
@Model, численная константа 1 – TINY
2 – SMALL
3 – COMPACT
4 – MEDIUM
5
LARGE
6 – HUGE
7 – FLAT
@CurSeg, строковая макропеременная Хранит имя текущего сегмента.
@fardata, @stack, строковая макропеременная Содержат соответствующие имена сегментов

Кроме знания макрофункций, нам так же понадобятся знания о блоках ветвлений
или просто IF блоках. Эти блоки позволяют исполнять тот или иной участок исходного
кода в зависимости от того, выполняется какое-либо условие или нет. Часто это
называют «Условным ассемблированием (компиляцией)», однако для MASM это нечто
большее, нежели простое управление компилятором, так как, вы уже поняли, мы
имеем дело, как с кодом машины, так и с макрокодом, который вычисляется и живёт
только во время компиляции.

Условный блок в MASM имеет следующий общий вид:

[IFDIRECTIVE]      условие
...
[ELSEDIRECTIVE] условие
...
ELSE
...
ENDIF

Если выражение «Условие» равно истине, то выполняется блок кода, идущий после
условной директивы, иначе управление передаётся на следующий оператор за блоком.
[IFDIRECTIVE]/[ELSEDIRECTIVE] – могут быть той или иной директивой
условия. Стандартные директивы IF/ELSEIF/ELSE требуют,
чтобы выражение, стоящее при них, было целочисленным. Если вам необходимо проверять
другие условия, то для этого
в MASM предусмотрены специальные директивы.

Список [IFDIRECTIVE]/[ELSEDIRECTIVE]:

Блок Условие выполнения блока
IF выражение
ELSEIF выражение
ELSE
если выражение равно истине
IF1
ELSEIF1
если ассемблер выполняет первый проход
IF2
ELSEIF2
если ассемблер выполняет второй проход (устарело)
IFE выражение
ELSEIFE выражение
если выражение равно нулю
IFDEF выражение
ELSEIFDEF выражение

если идентификатор, который является результатом выражения, определен.

Идентификатором может быть макро, макропеременная, переменная, макроконстанта,
любой другой идентификатор.

При помощи этой директивы, можно проверить была ли определена та или
иная переменная, макро, константа.

IFDEF     PROGRAM_IMAGE_BASE
;; Выполняем действия если PROGRAM_IMAGE_BASE
;; определена

ELSE
IFNDEF выражение
ELSEIFNDEF выражение
если идентификатор не определён.
IFB строка
ELSEIFB строка

если строка пустая.

Строка считается пустой, если её длинна равна нулю,
либо она содержит одни пробелы. С помощью этой директивы можно определяет
присутствие/отсутствие необязательных макропараметров.

MyMacro      macro    param1,param2
IFB <param2>
;; Если макропараметр не определён,
;; генерируем ошибку

.ERR <Не определён параметр param2>
IFNB строка
ELSEIFNB строка
если строка не пуста.
IFDIF str1,str2
ELSEIFDIF str1,str2

если строки различны.

IFDIF <String>,<string>
  echo Этот код выполнится
  echo потому что строки различны
ENDIF
      
IFDIFI str1,str2
ELSEIFDIFI str1,str2

если строки различны (без учёта различий в регистре букв).

IFDIF  <String1>,<string2>
echo Этот код не выполнится
echo потому что строки Одинаковы
ENDIF
IFIDN str1,str2
ELSEIFIDN str1,str2

если строки одинаковы.

IFDIF  <String1>,<string2>
echo Этот код не выполнится
echo потому что строки Различны
ENDIF
IFIDN str1,str2
ELSEIFIDN str1,str2

если строки одинаковы (без учёта различий в регистре букв).

IFDIF  <String1>,<string2>
echo Этот код выполнится
echo потому что строки Одинаковы
ENDIF

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

Вы уже, наверное, убедились насколько полезна эта директива, позволяющая
заглянуть, а что именно происходит в недрах макроса, или посмотреть значения
макропеременных.

Кроме этого, есть ещё одна группа директив, без которой мы не сможем обойтись.
Не сможем потому, что макрофункции, или макросы, которые мы собираемся создавать
должны быть слегка умными, иначе говоря, иметь «защиту от дурака».

Если кто-то неправильно использует макрос, то код, полученный таким образом
может быть неправильным с точки зрения программиста, но не вызовет подозрений
у компилятора.
Поэтому макро не просто должен завершится, а и каким-то образом остановить
компиляцию программы с выдачей сообщения об ошибке.

Именно для этого и существует простой набор директив условной генерации
ошибки. Действуют они подобно условным блокам и директиве echo. Пример
безусловной
генерации ошибки:

.ERR <Ошибочка вышла, гражданин начальник>

Условная генерация ошибки, имеют ту же форму, что и IFDIRECTIVE в таблице
выше, однако последним дополнительным параметром является строка сообщения.
Например:

.ERRE	 выражение,<ошибка, если выражение равно нулю>
.ERRNZ выражение,<ошибка, если выражение не равно нулю>
.ERRDEF id,<ошибка, если id определен>
.ERRB строка,<ошибка, если строка пуста>
.ERRNB строка,<ошибка, если строка не пуста>
.ERRDIF str1,str2,<ошибка, если строки различны>
.ERRDIFI str1,str2,<ошибка, если строки различны (без учёта регистра)>
.ERRIDN str1,str2,<ошибка, если строки одинаковы>
.ERRIDNI str1,str2,<ошибка, если строки одинаковы (без учёта регистра)>

III.7. Символ макроподстановки

Ещё раз вернёмся к формальным параметрам макро. Как было сказано, при раскрытии
макроопределения препроцессор заменяет в теле макро формальные названия на
их величины. В MASM32 предусмотрено ещё одно средство подстановки макропараметров
– внутри строкового литерала.

Предположим нам нужно, чтобы макро генерировал строку: «label_xx». Где xx – это формальный параметр макро. Это можно сделать двумя способами:

@CatStr(label_,xx)	;;Вызов макрофункции конкантенации строк
или
label_&xx& ;;Использование символа макроподстановки

То есть если во время генерации макро, препроцессор встречает в его теле символ
«&», он анализирует строку после него. Если эта строка однозначно определяет
один из макропараметров, препроцессор заменяет выражение &макропараметр& на
значение макропараметра.

Следует отметить, что если макропараметр начинает или заканчивает литерал,
то
можно использовать только один символ «&»:

label_&xx
;;или ещё пример
label_&xx&&xx2 ;; Замена для двух макропараметров xx и xx2

III.8. Макроблоки

И, наконец, у читателя должен остаться единственный вопрос: «А как обрабатывать
переменные типа VARARG
»? Например, рассмотрим возможный макро для вызова функций
STDCALL:

stdcall		macro funname,params:VARARG

			    endm

Этот макро должен генерировать код вызова функции согласно конвенции STDCALL:

  1. Поместить параметры в стек в обратном порядке их определению.
  2. Вызвать функцию funname, предварительно видоизменив её имя по правилам
    STDCALL.

Получить видоизмененное имя функции по значению параметра funname можно
было бы при помощи символа макроподстановки.

          call	_&funname@(количество параметров * 4)

Но непонятно, как распознать параметры функции, которые представляют собой
строку, где значения разделены символом «,». Более того, не понятно,
как вообще можно получить эти параметры, и посчитать их число, ведь макропараметр
params – это одна строка. То есть при вызове макро:

stdcall win32fun,1,2,3 

Мы должны как-то определить количество параметров, а потом их значения.

Именно для решения этой задачи в MASM предусмотрены несколько специальных
макроопределений, которые можно назвать макроблоками.

Первый из них FOR позволяет получить значения элементов, разделённых в строке
символом «,».

FOR parameter[:REQ | :=default], string
statements
ENDM

Вспоминая С конструкцию FOR, вы сразу поймёте что это цикл, где значение parameter последовательно принимает значения элементов списка string.

Вот вам wonderful пример:

FOR parameter, <It’s, wonderful, wonderful, asm>
echo parameter
ENDM
ВЫВОД:
-=-=-=-=-=-=
It's
wonderful
wonderful
asm
-=-=-=--=-=-

А вот пример макрофункции, который подсчитывает число аргументов VARARG:

@ArgCount MACRO parmlist:VARARG
count = 0
FOR param, <parmlist>
count = count + 1
ENDM
EXITM count
ENDM

Вот в принципе, уже на основе этих знаний можно было бы организовать макрос
stdcall:

stdcall    macro funname,params:VARARG
count = 0
FOR param, <parmlist>
count = count + 1 ;; Считаем число параметров
push param ;; Помещаем их в стек
ENDM
;;Вызываем функцию
call ??? ;;А вот как это сделать?
endm

Ещё несколько минут необходимо для того, чтобы понять, что этот макро работает
неправильно. Хотя бы потому, что параметры помещаются в стек не так. Нужно
было бы помещать их от последнего к первому, а не от первого к последнему.
А, кроме того, ведь символ макроподстановки нельзя употреблять к макропеременной
count, потому что это не макропараметр, это макропеременная.

К сожалению, в MASM нет обратной конструкции FOR. Поэтому самый простой выход,
который напрашивается сам собой – это изменить порядок параметров в списке,
а потом только генерировать команды push.

Вторую проблему можно легко решить, воспользовавшись макрофункцией конкатенации
строк:

		call	@CatStr(_,funname,@,%(count*4))

С параметрами в стек будет посложнее. В принципе я бы решил эту задачу, если
бы MASM поддерживал бы такой тип макропеременных как массив. Но хотя MASM и
не поддерживает этот тип, его можно эмулировать.

count = 0
FOR param, <paramlist>
count = count + 1 ;; Считаем число параметров
@CatStr(var,%count) TEXTEQU <param>
ENDM

Как вы можете догадаться, в этом примере создаются макропеременные varXX,
которым присваиваются значения параметров. Теперь с той же лёгкостью можно
работать с этими переменными. Можно снова использовать цикл FOR, однако в данном
случае, было бы грамотней воспользоваться значением count, и выполнить цикл
столько раз, сколько записано в нашем счётчике параметров. Для этого мы воспользуемся
ещё одним макроблоком rept, о котором скажем позже:

nparams = count


		REPT    nparams            	;; Начало блока
               push	@CatStr(var,%count)
			count = count - 1
		ENDM

Блок REPT выполняется столько раз, сколько указано в nparams. Я ввёл эту дополнительную
макропеременную, для того, чтобы значение, указанное в REPT осталось неизменным.
Однако этого не нужно. Можно было бы написать и так:

REPT    count            	;; Начало блока
push @CatStr(var,%count)
count = count - 1
ENDM

Значение макропеременной count инициализирует цикл только один раз вначале,
после чего, она может, как угодно менять значение.

И ещё один макроблок, без которого нам невозможно будет реализовать макрос
для определения строк уникода, или макрос, который позволяет писать строки
OEM в
редакторе использующий кодировку win cp-1251 (например, при создании консольных
приложений).

Этот макроблок FORC:

FORC char, string
;;блок
ENDM

Блок FORC выполняется столько раз, сколько символов в строке string, при этом
макропараметр char равен текущему символу из строки.
Например, посчитать количество символов в строке можно было бы так:

count = 0
FORC char, <Сколько тут символов?>
count = count + 1
ENDM
%echo @CatStr(%count)

А вот так, можно было бы посчитать количество пробельных символов.

count = 0
FORC char, <Сколько тут символов?>
IFB <char>
count = count + 1
ENDIF
ENDM
%echo @CatStr(%count)

Упражнение:

TheSvin‘у, как и любому программисту, который часто имеет дело с битами,
было бы удобно записывать значения бит по группам, через пробел.

;;Вот так неудобно и ненаглядно
        mov eax,011110111011b
;;Вот так удобно и наглядно, но компилятор выдаст ошибку
;;Вариант1
        mov eax, 0111 101 1101 1b
;;А вот так вообще замечательно, только ML неправильно поймёт
;;Вариант2
        mov eax, [0111] [101] [1101] [1]b

Хорошо бы было написать некую макрофункцию, которая смогла бы позволить записывать
эти выражения:

		mov eax,nf(0111 101 1101 1b)

Напишите такую макрофункцию, которая позволила бы это делать. Напишите её
для первого и второго вариантов исполнения.

III.9. Отладка макроопределений и заключение

А напоследок… остаётся маленькая деталь.

И эта деталь не самая приятная. Отладка макроопределений и их испытания невозможны
под отладчиком. А, кроме того, если при генерации макро возникает ошибка,
то ML выдаёт её в жутком виде:

.start.asm(84) : error A2008: syntax error : in directive
MacroLoop(3): iteration 8: Macro Called From
.start.asm(84): Main Line Code

То есть он выдаёт относительную строку в макро MacroLoop(3), где эта ошибка
появилась. А если ещё макровызовы будут вложенными, то вам лучше не видеть
этой замечательной картины.

Единственной возможностью качественно и относительно легко отлаживать макро
– это употребление директивы echo.

На протяжении статьи вы не раз наблюдали примеры её использования. Но я снова
повторюсь:

;; Для макропараметров
echo macroparam
;; Для макропеременных типа строка или текстовых макро
%echo macrovar_string
;; Для целочисленных макропеременных, или макроконстант
%echo @CatStr(%macro_num)

Заметьте, чтобы вывести значение целочисленной макропеременной необходимо
воспользоваться макрофункцией @CatStr(), и перед аргументом указать оператор
%. Почему именно так обсуждалась в пункте III.2. Определение макро переменных
и строк.

Теперь вы знакомы с теорией использования макроопределений в MASM32, и сможете
смело приступать к разработке макро. Именно этим мы и займёмся в следующей
практической части нашего руководства, а так же заполним некоторые пробелы,
на которые не
обратили внимания здесь.

III.10. Абстрактный алгоритм анализа строки MASM (Дополнение)

1. Определены таблицы элементов:

Таблица переменных Хранит сведения о всех переменных модуля
Таблица меток Хранит список меток в коде.
Таблица процедур Хранит таблицу и прототип процедур
Список ключевых слов KEYLIST Хранит список ключевых слов, на которые реагирует ML
Таблица макрофункций Хранит тело всех макро, их имена и тип: макрофункция, или макро. Список
макропараметров
Таблица макросов -=-
Таблица макропеременных, или переменных времени компиляции Хранит тип макропеременной и её значение.
Всё остальное, что не включено  

2. Начальное состояние анализа строки.

3. Читать поток символов, пока не встретится символ возврата каретки без предыдущего
символа «/». Игнорировать часть строки после «;»

a. Определить наличие лексем первого уровня в строке:

i. Выделить все строковые литералы в кавычках, если только это не
выражение с TEXTEQU и символ комментария «;»
ii. Строковые литералы: <текст>
iii. Численные литералы: 1234, 1234h, 01011b
iv. Правильные литералы: строка из символов «A-Z,a-z,_0-9», но не
начинающаяся на цифру
v. Литералы разделители: «,.»
vi. Управляющие Литералы: «+-*» Правильные литералы: строка из символов
«A-Z,a-z,_0-9», но не начинающаяся на цифру

b. Проверить правильные литералы на совпадение в списке ключевых слов,
и определить схему выражения. В зависимости от схемы выражения, выполнить
или
пропустить:

i. Проверить правильные литералы на совпадение в списке макро (в зависимости
от способа вызова в списке макрофункций, или макросов)
ii. Проверить на наличие имени правильного литерала в таблице макропеременных.
iii. Осуществить вызов и замену макро и макропеременных, в соответствии
с выражением строки.
iv. Вычислить все выражения допустимые в ML (+-*).

c. Осуществить разбор схемы.

i. Если это определение процедуры, записать в таблице процедур имя
и прототип новой процедуры
ii. Если это макроопределение: анализировать его тело. Если найден
возвращаемый параметр, записать макроопределение в таблицу макрофункций,
иначе в таблицу
макросов.
iii. Если это определение EQU вычислить правую часть.

1. Если эта макропеременная уже есть в таблице макропеременных,
и её тип – числовой, выдать ошибку. Если эта макропеременная
имеет строковый
тип,
изменить
строку, на которую указывает свойство value этой макропеременной.
2. Если правая часть числовой литерал – записать EQU определение
в таблицу, и пометить его тип как числовой константы. Записать
в свойство
макропеременной
value значение указателя на строку. Записать свойство value
равным числу.
3. иначе EQU – переменная, имеющая указатель на строку. Записать
в значения свойства value указатель на строку.

iv. Если это выражение с «=» или подобное, выполнить замену
всех литералов на макроконстанты, переменные, вызов всех
макрофункций,
и только потом
выполнять выражение.

4. Перейти к анализу следующей строки.


archive

archive
New Member

Регистрация:
27 фев 2017
Публикаций:
532


WASM

From BetaArchive Wiki

Jump to:navigation, search

Article ID: 75601

Article Last Modified on 10/22/2003


  • Microsoft Macro Assembler 6.0 Standard Edition
  • Microsoft Macro Assembler 6.0a
  • Microsoft Macro Assembler 6.0b
  • Microsoft Macro Assembler 6.1 Standard Edition
  • Microsoft Macro Assembler 6.11 Standard Edition

This article was previously published under Q75601

SYMPTOMS

When initializing a structure in the Microsoft Macro Assembler (MASM), if the initializers are written on separate lines, one or more of the following errors may occur:

MASM 6.x A2045: missing angle bracket or brace in literal
MASM 6.x A2009: syntax error in expression
MASM 5.x A2105: expected: instruction, directive or label

RESOLUTION

To work around this problem, either use the backslash () line continuation character following a comma, or with MASM 6.0 and later use curly braces in place of the angle brackets. Curly braces are a legal substitute syntax for angle brackets. The sample code below illustrates the problem syntax and the workaround.

STATUS

Microsoft has confirmed this to be a problem in MASM versions 5.1, 5.1a, 6.0, 6.0a, 6.0b, 6.1, 6.1a, and 6.11. We are researching this problem and will post new information here in the Microsoft Knowledge Base as it becomes available.

MORE INFORMATION

Page 127 of the «Microsoft Macro Assembler Programmer’s Guide» from MASM 6.0 states:

The list of initializers can be broken only after a comma unless you use a line continuation character () at the end of the line.

The following sasmple code can be used to demonstrate the problem.

Sample Code

; Assemble options needed: /c

.MODEL small

name1 STRUCT
   sub1 DB 'item'
   sub2 DW ?
name1 ENDS

.DATA
;item3 name1 {'am',     ; assembles correctly
;             14}

;item4 name1 <'pm',    ; assembles correctly with the
;             18>       ; ()continuation character

item3 name1 <'am',      ; this generates an error
             14>        ; MASM 6.0 A2045: missing angle bracket or
                        ; brace in literal
                        ; MASM 5.1 A2105: expected: instruction,
                        ; directive or label

item4 name1 <'pm'      ; this generates an error
             18>        ; MASM 6.0 A2009: syntax error in expression
                        ; MASM 5.1 A2105: expected: instruction,
                        ; directive or label
.CODE
   mov ax, @data        ; initialize the ds register
   mov ds, ax
   mov ax, item3.sub2   ; for verifying the values
   mov ax, item4.sub2   ; of the initialization, in CodeView
   mov ax, 4C00h
   int 21h
END
                

Additional query words: 5.10 5.10a 6.00 6.00a 6.00b 6.10 6.10a buglist6.00a buglist6.00b buglist6.10 buglist6.10a buglist6.11

Keywords: KB75601

This topic has been deleted. Only users with topic management privileges can see it.

  • Hello,
    I am trying to build qtwebkit-stable (x64) from https://github.com/annulen/webkit.git with Qt 5.10(MSVC 2015 x64).

    I am trying build with following command:

    perl Tools/Scripts/build-webkit --qt --release --minimal --cmakeargs="-Wno-dev -DCMAKE_PREFIX_PATH=d:Qt5.10.0msvc2015_64 -Thost=x64 -DCMAKE_GENERATOR_PLATFORM=x64" -G "Visual Studio 14 2015 Win64"
    

    but ends with errors:

    "D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseALL_BUILD.vcxproj" (default target) (1) ->
    "D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceWebKit2DatabaseProcess.vcxproj" (default target) (4) ->
    "D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceWebKitWebKit.vcxproj" (default target) (5) ->
    "D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj" (default target) (6) ->
    (_MASM target) ->
      velInterpreterWin.asm(10): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : . [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpro
    j]
      velInterpreterWin.asm(11): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : sp [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpr
    oj]
      velInterpreterWin.asm(12): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : CAST [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcx
    proj]
      velInterpreterWin.asm(13): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : . [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpro
    j]
      velInterpreterWin.asm(14): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : CAST [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcx
    proj]
      velInterpreterWin.asm(15): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : . [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpro
    j]
      velInterpreterWin.asm(16): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : CAST [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcx
    proj]
      velInterpreterWin.asm(17): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : . [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpro
    j]
      velInterpreterWin.asm(18): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : . [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpro
    j]
      velInterpreterWin.asm(19): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      MASM : error A2045: missing angle bracket or brace in literal [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScr
    iptCoreJavaScriptCore.vcxproj]
      velInterpreterWin.asm(20): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : . [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpro
    j]
      velInterpreterWin.asm(21): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : > [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpro
    j]
      velInterpreterWin.asm(22): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      MASM : error A2170: directive must appear inside a macro [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCo
    reJavaScriptCore.vcxproj]
      velInterpreterWin.asm(23): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : . [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpro
    j]
      velInterpreterWin.asm(24): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : . [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpro
    j]
      velInterpreterWin.asm(25): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      MASM : error A2045: missing angle bracket or brace in literal [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScr
    iptCoreJavaScriptCore.vcxproj]
      velInterpreterWin.asm(26): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : result [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.v
    cxproj]
      velInterpreterWin.asm(27): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : decodeResult [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScript
    Core.vcxproj]
      velInterpreterWin.asm(28): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      MASM : error A2045: missing angle bracket or brace in literal [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScr
    iptCoreJavaScriptCore.vcxproj]
      velInterpreterWin.asm(29): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      MASM : error A2008: syntax error [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpro
    j]
      velInterpreterWin.asm(30): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      MASM : error A2170: directive must appear inside a macro [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCo
    reJavaScriptCore.vcxproj]
      velInterpreterWin.asm(31): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : . [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpro
    j]
      velInterpreterWin.asm(32): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : . [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpro
    j]
      velInterpreterWin.asm(33): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      MASM : error A2170: directive must appear inside a macro [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCo
    reJavaScriptCore.vcxproj]
      velInterpreterWin.asm(36): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : . [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpro
    j]
      velInterpreterWin.asm(37): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : . [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpro
    j]
      velInterpreterWin.asm(38): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : . [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpro
    j]
      velInterpreterWin.asm(39): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : . [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpro
    j]
      velInterpreterWin.asm(40): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      MASM : error A2045: missing angle bracket or brace in literal [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScr
    iptCoreJavaScriptCore.vcxproj]
      velInterpreterWin.asm(41): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : result [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.v
    cxproj]
      velInterpreterWin.asm(42): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : decodeResult [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScript
    Core.vcxproj]
      velInterpreterWin.asm(43): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      MASM : error A2045: missing angle bracket or brace in literal [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScr
    iptCoreJavaScriptCore.vcxproj]
      velInterpreterWin.asm(44): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : . [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpro
    j]
      velInterpreterWin.asm(45): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : . [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpro
    j]
      velInterpreterWin.asm(46): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : . [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpro
    j]
      velInterpreterWin.asm(47): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : CAST [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcx
    proj]
      velInterpreterWin.asm(48): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : . [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpro
    j]
      velInterpreterWin.asm(49): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : CAST [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcx
    proj]
      velInterpreterWin.asm(50): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : sp [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpr
    oj]
      velInterpreterWin.asm(54): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : DISPATCH_OPCODE [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScr
    iptCore.vcxproj]
      velInterpreterWin.asm(57): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : sp [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpr
    oj]
      velInterpreterWin.asm(58): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : . [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpro
    j]
      velInterpreterWin.asm(61): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : . [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpro
    j]
      velInterpreterWin.asm(62): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : t3 [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpr
    oj]
      velInterpreterWin.asm(63): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      MASM : error A2045: missing angle bracket or brace in literal [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScr
    iptCoreJavaScriptCore.vcxproj]
      velInterpreterWin.asm(64): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      MASM : error A2045: missing angle bracket or brace in literal [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScr
    iptCoreJavaScriptCore.vcxproj]
      velInterpreterWin.asm(65): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      MASM : error A2044: invalid character in file [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScri
    ptCore.vcxproj]
      velInterpreterWin.asm(66): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      MASM : error A2170: directive must appear inside a macro [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCo
    reJavaScriptCore.vcxproj]
      velInterpreterWin.asm(67): error A2071: initializer magnitude too large for specified size [D:CppProjectsqt-webkit-minimalwebkitWebKi
    tBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj]
      : error A2008 : syntax error : . [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpro
    j]
      C:Program Files (x86)MSBuildMicrosoft.Cppv4.0V140BuildCustomizationsmasm.targets(50,5): error MSB3721: Polecenie ml64.exe /c /nolo
    go /Zi /Fo"JavaScriptCore.dirReleaseLowLevelInterpreterWin.obj" /D"WIN32" /D"_WINDOWS" /D"NDEBUG" /D"BUILDING_JavaScriptCore" /D"BUILDING
    _WITH_CMAKE=1" /D"HAVE_CONFIG_H=1" /D"BUILDING_QT__=1" /D"QT_NO_EXCEPTIONS" /D"QT_USE_QSTRINGBUILDER" /D"QT_NO_CAST_TO_ASCII" /D"QT_ASCII_C
    AST_WARNINGS" /D"QT_DEPRECATED_WARNINGS" /D"QT_DISABLE_DEPRECATED_BEFORE=0x050000" /D"NOMINMAX" /D"UNICODE" /D"_UNICODE" /D"WINVER=0x601" /
    D"_HAS_EXCEPTIONS=0" /D"_CRT_SECURE_NO_WARNINGS" /D"_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1" /D"STATICALLY_LINKED_WITH_WTF" /D"QT_CORE_LI
    B" /D"QT_NO_DEBUG" /D"CMAKE_INTDIR="Release"" /I "D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCore" /I "D:
    CppProjectsqt-webkit-minimalwebkitSourceJavaScriptCore" /I "D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseDerivedSources
    ForwardingHeaders" /I "D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseDerivedSources" /I "D:CppProjectsqt-webkit-minimalwe
    bkitWebKitLibrarieswininclude" /I "D:CppProjectsqt-webkit-minimalwebkitWebKitBuildRelease" /I "D:CppProjectsqt-webkit-minimalweb
    kitSourceJavaScriptCore.." /I "D:CppProjectsqt-webkit-minimalwebkitSourceJavaScriptCoreAPI" /I "D:CppProjectsqt-webkit-minimalw
    ebkitSourceJavaScriptCoreForwardingHeaders" /I "D:CppProjectsqt-webkit-minimalwebkitSourceJavaScriptCoreassembler" /I "D:CppProje
    ctsqt-webkit-minimalwebkitSourceJavaScriptCoreb3" /I "D:CppProjectsqt-webkit-minimalwebkitSourceJavaScriptCoreb3air" /I "D:Cpp
    Projectsqt-webkit-minimalwebkitSourceJavaScriptCorebindings" /I "D:CppProjectsqt-webkit-minimalwebkitSourceJavaScriptCorebuiltin
    s" /I "D:CppProjectsqt-webkit-minimalwebkitSourceJavaScriptCorebytecode" /I "D:CppProjectsqt-webkit-minimalwebkitSourceJavaScrip
    tCorebytecompiler" /I "D:CppProjectsqt-webkit-minimalwebkitSourceJavaScriptCoredfg" /I "D:CppProjectsqt-webkit-minimalwebkitSour
    ceJavaScriptCoredisassembler" /I "D:CppProjectsqt-webkit-minimalwebkitSourceJavaScriptCoredisassemblerudis86" /I "D:CppProjectsq
    t-webkit-minimalwebkitSourceJavaScriptCoreftl" /I "D:CppProjectsqt-webkit-minimalwebkitSourceJavaScriptCoreheap" /I "D:CppProjec
    tsqt-webkit-minimalwebkitSourceJavaScriptCoredebugger" /I "D:CppProjectsqt-webkit-minimalwebkitSourceJavaScriptCoreinspector" /I
     "D:CppProjectsqt-webkit-minimalwebkitSourceJavaScriptCoreinspectoragents" /I "D:CppProjectsqt-webkit-minimalwebkitSourceJavaSc
    riptCoreinspectoraugmentable" /I "D:CppProjectsqt-webkit-minimalwebkitSourceJavaScriptCoreinspectorremote" /I "D:CppProjectsqt-w
    ebkit-minimalwebkitSourceJavaScriptCoreinterpreter" /I "D:CppProjectsqt-webkit-minimalwebkitSourceJavaScriptCorejit" /I "D:CppPr
    ojectsqt-webkit-minimalwebkitSourceJavaScriptCorellint" /I "D:CppProjectsqt-webkit-minimalwebkitSourceJavaScriptCoreparser" /I "
    D:CppProjectsqt-webkit-minimalwebkitSourceJavaScriptCoreprofiler" /I "D:CppProjectsqt-webkit-minimalwebkitSourceJavaScriptCorer
    eplay" /I "D:CppProjectsqt-webkit-minimalwebkitSourceJavaScriptCoreruntime" /I "D:CppProjectsqt-webkit-minimalwebkitSourceJavaSc
    riptCoretools" /I "D:CppProjectsqt-webkit-minimalwebkitSourceJavaScriptCorewasm" /I "D:CppProjectsqt-webkit-minimalwebkitSource
    JavaScriptCoreyarr" /I "D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseDerivedSourcesJavaScriptCore" /I "D:CppProjectsqt-w
    ebkit-minimalwebkitWebKitBuildReleaseDerivedSourcesJavaScriptCoreinspector" /I "D:CppProjectsqt-webkit-minimalwebkitSourceWTF" /
    I "D:Qt5.10.0msvc2015_64include" /I "D:Qt5.10.0msvc2015_64includeQtCore" /I "D:Qt5.10.0msvc2015_64.mkspecswin32-msvc" /W3 /e
    rrorReport:prompt  /Ta"D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseDerivedSourcesJavaScriptCoreLowLevelInterpreterWin.asm
    " has been completed; error code: 1. [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxpr
    oj]
    
        12 Warning(s)
        99 Error(s)
    

    but when I try compile with:

    perl Tools/Scripts/build-webkit --qt --release --minimal --cmakeargs="-Wno-dev -DCMAKE_PREFIX_PATH=d:Qt5.10.0msvc2015_64 -Thost=x64" -G "Visual Studio 14 2015 Win64"
    

    other errors appers:

    "D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseALL_BUILD.vcxproj" (default target) (1) ->
    "D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceWebKit2DatabaseProcess.vcxproj" (default target) (4) ->
    "D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceWebKitWebKit.vcxproj" (default target) (5) ->
    "D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreJavaScriptCore.vcxproj" (default target) (6) ->
    "D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaScriptCoreLLIntOffsetsExtractor.vcxproj" (default target) (7) ->
    (Link target) ->
      LINK : fatal error LNK1181: cannot open input file 'icudt.lib' [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceJavaSc
    riptCoreLLIntOffsetsExtractor.vcxproj]
    
    
    "D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseALL_BUILD.vcxproj" (default target) (1) ->
    "D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseToolsImageDiffImageDiff.vcxproj" (default target) (18) ->
      Qt5Core.lib(Qt5Core.dll) : fatal error LNK1112: module machine type 'x64' conflicts with target machine type 'X86' [D:CppProjectsqt-web
    kit-minimalwebkitWebKitBuildReleaseToolsImageDiffImageDiff.vcxproj]
    
    
    "D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseALL_BUILD.vcxproj" (default target) (1) ->
    "D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseToolsTestWebKitAPITestWTF.vcxproj" (default target) (22) ->
      LINK : fatal error LNK1181: cannot open input file 'icudt.lib' [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseToolsTestWeb
    KitAPITestWTF.vcxproj]
    
        10 Warning(s)
        3 Error(s)
    

    I suppose that script ‘build-webkit’ is trying to build 32bit version, because he is searching for ‘icudt.lib’ in ‘d:CppProjectsqt-webkit-minimalwebkitWebKitLibrarieswinlib32’.

    How can I compile qtwebkit 64bit with MSVC 2015?

  • Hi and welcome to devnet,

    What command line prompt did you start from ?

  • @SGaist said in QtWebKit — cannot build qtwebkit-stable from https://github.com/annulen/webkit.git:

    Hi and welcome to devnet,
    What command line prompt did you start from ?

    I started from
    -cmd.exe

    next I executed

    "perl Tools/Scripts/build-webkit --qt --release --minimal --cmakeargs="-Wno-dev -DCMAKE_PREFIX_PATH=d:Qt5.10.0msvc2015_64 -Thost=x64 -DCMAKE_GENERATOR_PLATFORM=x64" -G "Visual Studio 14 2015 Win64"
    

    which gives me 99 errors (see my first post).

    then I deleted contents in ‘WebKitBuild’ directory and executed following:

    perl Tools/Scripts/build-webkit --qt --release --minimal --cmakeargs="-Wno-dev -DCMAKE_PREFIX_PATH=d:Qt5.10.0msvc2015_64 -Thost=x64" -G "Visual Studio 14 2015 Win64"
    

    but this gives me 3 errors (see my first post).

    Of course earlier I installed:
    -Visual Studio Community 2015
    -Qt 5.10 MSVC 2015 x64,
    -CMake 3.10.1,
    -Ruby 2.5.0,
    -ActivePerl 5.24.3,
    -Python 2.7.14,
    -and I also cloned http://code.qt.io/cgit/qt/qt5.git and added gnuwin32/bin from cloned repository into %PATH%.

    At the beginning of the script execution I have this log:

    perl Tools/Scripts/build-webkit --qt --release --minimal --cmakeargs="-Wno-dev -DCMAKE_PREFIX_PATH=d:Qt5.10.0msvc2015_64 -Thost=x64 -DCMAKE_GENERATOR_PLATFORM=x64" -G "Visual Studio 14 2015 Win64"
    Checking Last-Modified date of qtwebkit-libs-win.zip...
    Located a file of type application/zip, of size 127044099.
    Current qtwebkit-libs-win is up to date
    Not searching for unused variables given on the command line.
    -- Building for: Visual Studio 14 2015
    -- The C compiler identification is MSVC 19.0.24215.1
    -- The CXX compiler identification is MSVC 19.0.24215.1
    -- Check for working C compiler: D:/VisualStudio2015/VC/bin/amd64/cl.exe
    -- Check for working C compiler: D:/VisualStudio2015/VC/bin/amd64/cl.exe -- works
    -- Detecting C compiler ABI info
    -- Detecting C compiler ABI info - done
    -- Check for working CXX compiler: D:/VisualStudio2015/VC/bin/amd64/cl.exe
    -- Check for working CXX compiler: D:/VisualStudio2015/VC/bin/amd64/cl.exe -- works
    -- Detecting CXX compiler ABI info
    -- Detecting CXX compiler ABI info - done
    -- Detecting CXX compile features
    -- Detecting CXX compile features - done
    -- Found BISON: D:/CppProjects/qt5-supermod/qt5/gnuwin32/bin/bison.exe (found suitable version "3.0", minimum required is "2.1")
    -- Found Gperf: D:/CppProjects/qt5-supermod/qt5/gnuwin32/bin/gperf.exe (Required is at least version "3.0.1")
    -- Found Perl: D:/Perl64/bin/perl.exe (found suitable version "5.24.3", minimum required is "5.10.0")
    -- Found PythonInterp: D:/Python27/python.exe (found suitable version "2.7.14", minimum required is "2.7.0")
    -- Could NOT find Ruby (missing: RUBY_LIBRARY) (found suitable version "2.5.0", minimum required is "1.9")
    -- Looking for include file features.h
    -- Looking for include file features.h - not found
    -- Disabling ENABLE_DFG_JIT since ENABLE_JIT is disabled.
    -- Disabling ENABLE_MEDIA_CONTROLS_SCRIPT since ENABLE_VIDEO is disabled.
    -- Found Sqlite: D:/CppProjects/qt-webkit-minimal/webkit/WebKitLibraries/win/include
    -- Looking for pthread.h
    -- Looking for pthread.h - not found
    -- Found Threads: TRUE
    -- Found JPEG: D:/CppProjects/qt-webkit-minimal/webkit/WebKitLibraries/win/lib64/libjpeg.lib
    -- Found ZLIB: D:/CppProjects/qt-webkit-minimal/webkit/WebKitLibraries/win/lib64/zlib.lib (found version "1.2.8")
    -- Found PNG: D:/CppProjects/qt-webkit-minimal/webkit/WebKitLibraries/win/lib64/libpng.lib (found version "1.6.20")
    -- Could NOT find PkgConfig (missing: PKG_CONFIG_EXECUTABLE)
    -- Found ICU header files in D:/CppProjects/qt-webkit-minimal/webkit/WebKitLibraries/win/include
    -- Found ICU libraries: D:/CppProjects/qt-webkit-minimal/webkit/WebKitLibraries/win/lib64/sicuuc.lib
    -- Found LibXml2: D:/CppProjects/qt-webkit-minimal/webkit/WebKitLibraries/win/lib64/libxml2.lib (found suitable version "2.9.3", minimum req
    uired is "2.8.0")
    -- Could NOT find Fontconfig (missing: FONTCONFIG_LIBRARIES FONTCONFIG_INCLUDE_DIR)
    -- Could NOT find PkgConfig (missing: PKG_CONFIG_EXECUTABLE)
    -- Found WEBP: D:/CppProjects/qt-webkit-minimal/webkit/WebKitLibraries/win/include
    -- Looking for QT_OPENGL_DYNAMIC
    -- Looking for QT_OPENGL_DYNAMIC - found
    -- Qt OpenGL implementation: DynamicGL
    -- Qt OpenGL libraries: Qt5::Gui_GLESv2
    -- Qt EGL libraries: Qt5::Gui_EGL
    -- The following OPTIONAL packages have been found:
    
     * WebP
     * Qt5OpenGL (required version >= 5.2.0)
    
    -- The following REQUIRED packages have been found:
    
     * BISON (required version >= 2.1)
     * Gperf (required version >= 3.0.1)
     * Perl (required version >= 5.10.0)
     * PythonInterp (required version >= 2.7.0)
     * Sqlite
     * Threads
     * JPEG
     * PNG
     * ZLIB
     * ICU
     * LibXml2 (required version >= 2.8.0)
     * Qt5Core
     * Qt5Gui
     * Qt5Network
     * Qt5Widgets
     * Qt5Test
     * Qt5QuickTest
     * Qt5PrintSupport
       Required for ENABLE_PRINT_SUPPORT=ON
     * Qt5Qml (required version >= 5.10.0)
     * Qt5Quick
     * Qt5WebChannel
     * Qt5 (required version >= 5.2.0)
     * Ruby (required version >= 1.9)
    
    -- The following OPTIONAL packages have not been found:
    
     * Fontconfig
     * PkgConfig
    
    -- Installing in the same prefix as Qt, adopting their path scheme.
    -- Using platform-specific CMakeLists: D:/CppProjects/qt-webkit-minimal/webkit/Source/WTF/wtf/PlatformQt.cmake
    -- The ASM_MASM compiler identification is MSVC
    -- Found assembler: D:/VisualStudio2015/VC/bin/amd64/ml64.exe
    -- Using platform-specific CMakeLists: D:/CppProjects/qt-webkit-minimal/webkit/Source/JavaScriptCore/PlatformQt.cmake
    -- Using platform-specific CMakeLists: D:/CppProjects/qt-webkit-minimal/webkit/Source/JavaScriptCore/shell/PlatformQt.cmake
    -- Using platform-specific CMakeLists: D:/CppProjects/qt-webkit-minimal/webkit/Source/WebCore/PlatformQt.cmake
    -- Using platform-specific CMakeLists: D:/CppProjects/qt-webkit-minimal/webkit/Source/WebKit/PlatformQt.cmake
    -- Using platform-specific CMakeLists: D:/CppProjects/qt-webkit-minimal/webkit/Source/WebKit2/PlatformQt.cmake
    -- Using platform-specific CMakeLists: D:/CppProjects/qt-webkit-minimal/webkit/Source/PlatformQt.cmake
    -- Using platform-specific CMakeLists: D:/CppProjects/qt-webkit-minimal/webkit/Tools/PlatformQt.cmake
    -- Using platform-specific CMakeLists: D:/CppProjects/qt-webkit-minimal/webkit/Tools/DumpRenderTree/PlatformQt.cmake
    -- Using platform-specific CMakeLists: D:/CppProjects/qt-webkit-minimal/webkit/Tools/ImageDiff/PlatformQt.cmake
    -- Using platform-specific CMakeLists: D:/CppProjects/qt-webkit-minimal/webkit/Tools/TestWebKitAPI/PlatformQt.cmake
    -- Enabled features:
    --  ENABLE_ACCELERATED_2D_CANVAS ............ OFF
    --  ENABLE_ALLINONE_BUILD                     OFF
    --  ENABLE_API_TESTS ........................ ON
    --  ENABLE_CSS_GRID_LAYOUT                    OFF
    --  ENABLE_DATABASE_PROCESS ................. ON
    --  ENABLE_DATALIST_ELEMENT                   OFF
    --  ENABLE_DEVICE_ORIENTATION ............... OFF
    --  ENABLE_DRAG_SUPPORT                       ON
    --  ENABLE_FULLSCREEN_API ................... OFF
    --  ENABLE_GAMEPAD_DEPRECATED                 OFF
    --  ENABLE_GEOLOCATION ...................... OFF
    --  ENABLE_ICONDATABASE                       OFF
    --  ENABLE_INDEXED_DATABASE ................. OFF
    --  ENABLE_INSPECTOR_UI                       ON
    --  ENABLE_JIT .............................. OFF
    --  ENABLE_LEGACY_WEB_AUDIO                   OFF
    --  ENABLE_LINK_PREFETCH .................... OFF
    --  ENABLE_MEDIA_SOURCE                       OFF
    --  ENABLE_NETSCAPE_PLUGIN_API .............. OFF
    --  ENABLE_OPENGL                             ON
    --  ENABLE_PRINT_SUPPORT .................... ON
    --  ENABLE_QT_GESTURE_EVENTS                  ON
    --  ENABLE_QT_WEBCHANNEL .................... ON
    --  ENABLE_SAMPLING_PROFILER                  OFF
    --  ENABLE_SPELLCHECK ....................... ON
    --  ENABLE_TOUCH_EVENTS                       OFF
    --  ENABLE_VIDEO ............................ OFF
    --  ENABLE_WEBKIT2                            ON
    --  ENABLE_WEB_AUDIO ........................ OFF
    --  ENABLE_X11_TARGET                         OFF
    --  ENABLE_XSLT ............................. OFF
    --  USE_GSTREAMER                             OFF
    --  USE_LIBHYPHEN ........................... OFF
    --  USE_MEDIA_FOUNDATION                      OFF
    --  USE_QT_MULTIMEDIA ....................... OFF
    --  USE_SYSTEM_MALLOC                         1
    --  USE_WOFF2 ............................... ON
    -- Configuring done
    
  • Why not start from the Visual Studio pre-configured command line ?

  • Please don’t use --minimal, it is not supported. Amongst other effects, this option disables JIT, which doesn’t work on Windows.

    Instead, disable options that you certainly don’t need, e.g. —no-video.

  • @Konstantin-Tokarev said in QtWebKit — cannot build qtwebkit-stable from https://github.com/annulen/webkit.git:

    Please don’t use —minimal, it is not supported. Amongst other effects, this option disables JIT, which doesn’t work on Windows.
    Instead, disable options that you certainly don’t need, e.g. —no-video.

    Thanks. I removed —minimal and got 1 error:

    perl Tools/Scripts/build-webkit --qt --release --cmakeargs="-Wno-dev -DCMAKE_PREFIX_PATH=d:Qt5.10.0msvc2015_64 -Thost=x64 -DCMAKE_GENERATOR_PLATFORM=x64" -G "Visual Studio 14 2015 Win64"
    ...
    "D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseALL_BUILD.vcxproj" (default target) (1) ->
    "D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceWebKit2DatabaseProcess.vcxproj" (default target) (4) ->
    "D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceWebKitWebKit.vcxproj" (default target) (5) ->
    "D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceWebKit2WebKit2.vcxproj" (default target) (14) ->
    (ClCompile target) ->
      D:CppProjectsqt-webkit-minimalwebkitSourceWebKit2PlatformIPCwinConnectionWin.cpp(32): fatal error C1083: Cannot open include fil
    e: 'wtf/text/win/WCharStringExtras.h': No such file or directory [D:CppProjectsqt-webkit-minimalwebkitWebKitBuildReleaseSourceWebKit
    2WebKit2.vcxproj]
    
        183 Warning(s)
        1 Error(s)
    

    What should I do?

  • @ex_it You should build qtwebkit-5.212 branch, not qtwebkit-stable. See readme.

  • @Konstantin-Tokarev said in QtWebKit — cannot build qtwebkit-stable from https://github.com/annulen/webkit.git:

    @ex_it You should build qtwebkit-5.212 branch, not qtwebkit-stable. See readme.

    I still have same one compile error after switch to qtwebkit-5.212 branch:

    dev@komp MINGW64 /d/CppProjects/qt-webkit-minimal/webkit (qtwebkit-5.212)
    $ git log
    commit aad6131617cdccc6f5173199394c1a8314fb7202 (grafted, HEAD -> qtwebkit-5.212, origin/qtwebkit-stable, origin/HEAD, qtwebkit-stable)
    Author: Konstantin Tokarev <annulen@yandex.ru>
    Date:   Thu Jan 11 05:53:21 2018 +0300
    
        REGRESSION(dc9ff80e6): macOS frameworks are installed without headers
    
  • Понравилась статья? Поделить с друзьями:
  • Error an unexpected network error occurred
  • Error an unexpected error occurred https registry yarnpkg com not found
  • Error an object could not be cloned
  • Error an nvidia kernel module nvidia drm appears to already be loaded in your kernel
  • Error an exception occurred in the script