Как писать на ассемблере в Visual Studio 2019

Обновлено: 20.11.2024

Необходимое условие

В этой статье мы получили представление о создании как EXE, так и DLL с помощью MASM в Visual Studio. Итак, новички должны иметь краткие знания об этих технологиях:

  • Visual Studio 2010 или более поздняя версия
  • Библиотека SDK MASM (Microsoft Macro Assembler)
  • Основные навыки программирования на ассемблере
  • VC++

Разработка EXE с помощью MASM

Открытие нового проекта

Нам нужно будет создать решение проекта VC++, которое позже будет сопровождаться файлом ассемблерного кода. Поэтому откройте Visual Studio и выберите Пустой проект типа шаблона VC++. Нет необходимости создавать подкаталог для этого пустого решения, поэтому снимите соответствующий флажок следующим образом:

После создания test_masm решения типа VC++ перейдите в обозреватель решений и щелкните правой кнопкой мыши, чтобы выбрать параметр Build Customization следующим образом:

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

Код сборки

Как мы уже говорили ранее, VS 2o1o не предоставляет шаблоны файлов сборки, однако выберите проект в обозревателе решений и щелкните правой кнопкой мыши, чтобы добавить текстовый файл, которому будет предоставлено расширение *.ASM следующим образом:

Теперь в наше решение test_masm добавлен пустой файл text.asm. Откройте его и вставьте следующий ассемблерный код, отвечающий за отображение окна сообщения, следующим образом:

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

Обязательные конфигурации проекта

Успешное выполнение файла ассемблерного кода в Visual Studio IDE зависит от файла внешней библиотеки, который будет доступен в MASM SDK. Следовательно, выберите проект Properties, щелкнув его правой кнопкой мыши в обозревателе решений. Здесь выберите Общие, развернув Linker и в Дополнительные каталоги библиотек вставьте путь к include, lib и макросы следующим образом:

Затем перейдите в раздел Input в Linker и укажите ссылку на файл masm32.lib в качестве дополнительных зависимостей:

Для таких манипуляций не требуется создавать файл манифеста, поэтому отключите его следующим образом:

Теперь перейдите в System из компоновщика и установите Windows в разделе subsystem следующим образом:

Наконец, настройте точку входа кода как начало от параметра Дополнительно в Компоновщике, который определяет поток выполнения кода. Мы можем определить точку входа в файл ASM из раздела .code.

Теперь перейдите в раздел Microsoft Macro Assembly из свойств решения, которое появляется в тот момент, когда мы добавляем файл сборки в каталог решения, иначе он будет скрыт. Здесь задайте имя каталога, в котором ранее был установлен MASM SDK, следующим образом:

Наконец все готово и решение скомпилировано. Если вся конфигурация верна, то в папке Debug решения создается файл test_masm.exe.

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

Пришло время протестировать исполняемый файл. При нажатии на исполняемый файл «Hello World!» окно сообщения будет выглядеть следующим образом:

Мы даже можем отлаживать ассемблерный код, вставляя точку останова в качестве определенного места, и через окно «Регистрация» в меню «Отладка» мы можем наблюдать за всеми регистрами ЦП с соответствующими флагами следующим образом:

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

Хотя этот раздел не относится к этой статье, но просто для ознакомления, мы можем дизассемблировать любой файл C++ в соответствующий код ASM. В интегрированную среду разработки Visual Studio встроен параметр Disassembly, который очень полезен для обнаружения ошибок во время выполнения, таких как переполнение буфера в коде, путем преобразования файла исходного кода в файл кода сборки следующим образом:

Разработка DLL с помощью MASM

Как мы все знаем, DLL-файлы — это библиотеки, содержащие определения методов. Точка входа обычно отсутствует в файле DLL. Следовательно, мы должны изменить этот параметр следующим образом:

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

[простой]
включить masm32includemasm32rt.inc

.data
dLoading BYTE «ПРИВЕТ, DLL загружается…..», 0
dUnloading BYTE «DLL выгружается. ", 0
dOrdinal BYTE "До свидания", 0

.данные?
hInst DWORD ?

.code
testingMethod proc hInstDLL:DWORD, fdwReason:DWORD, lpvReserved:DWORD

.if fdwReason == DLL_PROCESS_ATTACH
вызов MessageBox, HWND_DESKTOP, смещение dLoading, NULL, MB_OK

отправить hInstDLL
отправить hInst

mov eax, TRUE
ret

.elseif fdwReason == DLL_PROCESS_DETACH
вызов MessageBox, HWND_DESKTOP, смещение dUnloading, NULL, MB_OK

.elseif fdwReason == DLL_THREAD_ATTACH

.elseif fdwReason == DLL_THREAD_DETACH

ret
testingMethod endp
ProcByOrdinal proc
вызов MessageBox, NULL, смещение dOrdinal, NULL, NULL
ret
ProcByOrdinal endp

метод завершения тестирования
[/plain]

Наконец, скомпилируйте эту программу и test_masm_dll. Файл DLL будет создан в папке Debug, на которую можно ссылаться в программе C++ или в самой клиентской программе MASM.

Заключение

Создание проекта сборки x64 в Visual Studio 2019 может оказаться не таким простым делом при использовании большинства современных компиляторов.

Я покажу вам пошаговое руководство, чтобы получить полностью работающий проект сборки.

Это не так, так как я также покажу вам, как исправить распространенные неразрешенные внешние ссылки (чаще всего с printf), и последний пример!

Предварительные условия

Давайте настроим наш проект Assembly x64 в Visual Studio 2019!

Откройте Visual Studio 2019.

Создайте проект классического консольного приложения C++.

Как только ваш проект будет готов, измените его с версии x86 на версию x64.

Щелкните правой кнопкой мыши свое решение -> Создать персонализацию

Проверьте масм, как на этом изображении.

Пришло время добавить исходный файл сборки!

Щелкните правой кнопкой мыши исходную папку и добавьте новый элемент.

Затем просто напишите имя файла сборки с расширением .asm !

Пришло время правильно настроить входной файл .cpp, чтобы включить необходимые библиотеки.

Добавьте эти включения в основной файл .cpp:

Давайте исправим неразрешенные внешние ссылки!

В последних версиях компиляторов многие стандартные функции, такие как printf, scanf и другие, не объявлены как внешние, что не позволяет вам использовать их в файлах сборки. Давайте это исправим.

Щелкните правой кнопкой мыши решение -> Свойства

Найдите параметр Компоновщик и измените Дополнительные зависимости, как показано на этом изображении:

Эти две устаревшие библиотеки решат проблему, поскольку они объявляют функции (такие как printf, scanf) как внешние и поэтому их можно использовать снаружи!

  • legacy_stdio_definitions.lib
  • legacy_stdio_wide_specifiers.lib

Сборочный проект Visual Studio: простой пример

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

Мы наладим связь между файлами .cpp и .asm. В частности, мы сможем вызывать функции, написанные на ассемблере, из нашего файла .cpp.

Этот форум перенесен в раздел вопросов и ответов Майкрософт. Посетите Microsoft Q&A, чтобы публиковать новые вопросы.

Вопрос:

Вопрос

Я убежденный программист masm. Я терпеливо ждал годами, пока Microsoft решит проблему отсутствия хороших инструкций по настройке Visual Studio для MASM. Не пора ли поручить сертифицированным программистам MASM написать хорошую процедуру для этой цели?

Сначала я пытался научиться выполнять эту задачу с помощью vs2015, и в конце концов мне это удалось. Затем, когда вы выпустили vs2017, мне, к моему огорчению, пришлось переучиваться заново. Теперь с vs2019 мне пришлось отказаться от обучения, потому что код vs2017 не применим должным образом к vs2019. Должен ли я задуматься, не трачу ли я время/деньги на ожидание?

В любом случае, я думаю, что Visual Studio значительно выросла с момента своего первого выпуска. При правильном управлении он должен стать вашим лучшим источником дохода. Только не забывайте все свои древние кодеры MASM. ПОЖАЛУЙСТА.

Тем временем, думаю, мне придется подождать или в конце концов переключиться на Linux или Nasm.

Все ответы

Я использую одни и те же инструкции для включения ассемблера в Visual Studio, начиная с Visual Studio 2010.

Поэтому, если вы не используете устаревшую версию MASM, предоставляемую MASM32 SDK (которая является версией ассемблера из Visual C++ 6 IIRC), заставить MASM работать в Visual Studio довольно просто.

1) Включите MASM для проекта в настройках сборки. При этом будет использоваться версия MASM, связанная с Visual Studio, поэтому для Visual Studio 2019 с обновлением 2 (16.2.0) это версия 14.22.27905.0.

C:\Program Files (x86)\Microsoft Visual Studio\2019\Community>ml
Microsoft (R) Macro Assembler Version 14.22.27905.0
Авторское право (C) Microsoft Corporation. Все права защищены.

C:\Program Files (x86)\Microsoft Visual Studio\2019\Community>

C:\Program Files (x86)\Microsoft Visual Studio\2019\Community>ml64
Microsoft (R) Macro Assembler (x64) Версия 14.22.27905.0
Авторское право (C) Microsoft Corporation. Все права защищены.

Это заставит Visual Studio запускать ML.exe или ML64.exe или даже armasm/armasm64.exe, если вы этого хотите, для каждого файла с расширением .asm.

2) При необходимости настройте пути включения. Следует помнить, что MASM также использует переменную среды INCLUDE, поэтому пути для C/C++ будут использоваться MASM.

И вот. Это Visual Studio, настроенная для сборки с использованием MASM.

Что вы хотите этим сказать?Сборка x86 - это сборка x86, сборка x64 - это сборка x64. Если вы не делаете что-то глупое, например, пытаетесь собрать 32-битный файл сборки в 64-битном проекте или 64-битный файл проекта в 32-битном проекте, тогда нет ничего, что изменилось бы настолько, чтобы вызвать проблемы. Самое большое изменение, о котором я недавно слышал, — это добавление новых инструкций, таких как набор инструкций AVX512.

Это подпись. Любые приведенные примеры не предназначены для проверки ошибок или демонстрации лучших практик. Они предназначены только для того, чтобы проиллюстрировать точку зрения. Я также могу дать неэффективный код или представить некоторые проблемы, чтобы препятствовать копированию/вставке кода. Это потому, что основная цель моих постов — помочь в процессе обучения.

Эта запись блога представляет собой пошаговое руководство по вставке кода языка ассемблера x64 и x86 в проект Visual Studio C++. В этом примере я буду использовать Visual Studio 2019, Community Edition.

Для краткости я предполагаю, что читатель знаком с инструкциями языка ассемблера x64 и x86, а также с соглашениями о вызовах Windows.

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

Прежде чем мы сможем начать добавлять некоторый код на ассемблере в наш проект Visual Studio C++, я должен указать, что с момента появления процессоров x64 компилятор Microsoft больше не позволяет встроенное включение кода ассемблера с ключевым словом __asm.< /p>

Таким образом, единственный способ добавить наш код на языке ассемблера — включить его в отдельный файл(ы). Каждый файл также должен быть включен в правильную конфигурацию сборки, чтобы убедиться, что он соответствует правильному синтаксису, в зависимости от выбранной разрядности ЦП проекта C++.

Давайте рассмотрим процесс шаг за шагом:

  1. Создайте проект C++ с помощью Visual Studio.
  2. Начнем с добавления в сборку Microsoft Macro Assembler. Щелкните правой кнопкой мыши имя проекта в обозревателе решений, затем перейдите в «Зависимости сборки» -> «Настройки сборки» и обязательно отметьте masm(.targets, .props) в списке и нажмите «ОК»:

Щелкните правой кнопкой мыши имя проекта в обозревателе решений, выберите «Добавить» -> «Новый элемент», затем выберите в списке «Файл заголовка» (.h) и дайте ему имя. Обязательно укажите расширение .asm. Для удобства чтения назовем этот файл asm64.asm :

В качестве теста я добавлю функцию asm_func, которая будет вызывать API MessageBox, но перед этим она вызовет нашу функцию C++ GetMsgBoxType. Итак, давайте закодируем все это:

Обратите внимание, что я использую префикс __imp_ при вызове API MessageBoxA. Прочтите этот пост в блоге, чтобы понять значение этого префикса.

Щелкните правой кнопкой мыши имя проекта в обозревателе решений, выберите «Добавить» -> «Новый элемент», затем выберите в списке «Файл заголовка» (.h) и дайте ему имя. Обязательно укажите расширение .asm. Для удобства чтения назовем этот файл asm32.asm :

Обратите внимание, что из-за соглашения о вызовах __fastcall я должен украшать имя функции asm_func префиксом и суффиксом @, а также заканчивать его количеством байтов, которые передаются в эту функцию.

Аналогичный метод применяется к вызову MessageBoxA, использующему соглашение о вызовах __stdcall. Однако в этом случае к нему добавляется _ и суффикс @, а за ним следует количество байтов, которые передаются в этот API в качестве параметров.

Кроме того, обратите внимание, что я также использовал __imp_ в этом вызове API, чтобы избежать вызова ненужного вызова JMP. Мне также пришлось удалить ведущее подчеркивание из него, чтобы учесть объявление .model C, которое будет указывать компилятору MASM добавлять _ к именам функций по умолчанию. Это зачаток устаревшего компилятора x86 MASM.

Вызов директивы OPTION LANGUAGE: SYSCALL перед объявлением функции asm_func позволяет избежать автоматического префикса имен функций с символами подчеркивания.

Это исключит 32-разрядный файл на языке ассемблера из 64-разрядной сборки конфигурации.

Это исключит 64-битный файл на языке ассемблера из 32-битной сборки конфигурации.

Обратите внимание, что я объявляю нашу функцию языка ассемблера asm_func с помощью ключевого слова extern "C". Это заставит его придерживаться схемы искажения C-имени. Кроме того, я также объявляю нашу функцию обратного вызова GetMsgBoxType с тем же ключевым словом, чтобы мы могли ссылаться на нее по имени из нашего кода сборки.

И, наконец, вот видеообзор того, что вы только что прочитали выше, с некоторыми дополнительными подробностями:

Это был краткий обзор того, как можно добавить код на языке ассемблера в ваши проекты C++, скомпилированные с помощью Microsoft Visual Studio. Обратите внимание: чтобы сделать этот пост кратким, я не стал вдаваться в особенности написания самого кода ассемблера. Для этого обратитесь к различным руководствам.

Читайте также: