Ассемблер
Как программировать на ассемблере в Visual Studio
Программировать на ассемблере в Visual Studio удобнее всего через MASM и C++ проект. Вы создаете .asm-файл, включаете сборку MASM, пишете процедуру на ассемблере и вызываете ее из C++. Такой подход практичнее, чем пытаться сделать весь проект только из asm-файлов: Visual Studio хорошо помогает со сборкой, линковкой и отладкой
Базовая схема
- Установить workload
Desktop development with C++. - Создать C++ Console App.
- Включить MASM Build Customization.
- Добавить
.asm-файл. - Написать процедуру.
- Объявить ее в C++ через
extern "C". - Собрать проект и поставить breakpoint.
Эта схема подходит для учебных примеров, где ассемблерная функция делает маленькую операцию: сложение, умножение, работу с регистрами
Пример ассемблерной функции
Файл math.asm:
.code
AddTwo PROC
mov eax, ecx
add eax, edx
ret
AddTwo ENDP
END
Для x64 Windows первые целочисленные аргументы приходят в rcx, rdx, r8, r9. Если функция принимает int, можно работать с младшими частями ecx и edx, а результат вернуть через eax
Файл C++:
#include <iostream>
extern "C" int AddTwo(int a, int b);
int main() {
std::cout << AddTwo(5, 3) << std::endl;
}
Ожидаемый вывод:
8
Что важно понимать про x64
В Visual Studio для x64 нельзя пользоваться inline asm так же, как в старых 32-битных примерах. Поэтому нормальный путь — отдельный .asm-файл. Также важно соблюдать calling convention: какие регистры можно менять свободно, какие нужно сохранять, где возвращается результат
Если вы меняете регистры, которые функция должна сохранять, сохраните их через стек и восстановите перед ret
Как отлаживать
Поставьте breakpoint в C++ перед вызовом функции и зайдите внутрь через Step Into. Если Visual Studio не переходит в asm-файл, проверьте, участвует ли файл в сборке и создан ли символ отладки
Для первых примеров полезно смотреть окна регистров и дизассемблирования. Так видно, что ecx и edx действительно содержат аргументы
Когда переходить от настройки к коду
Установка MASM — это только подготовка инструментов. Программирование — это уже организация проекта: как написать функцию, как вызвать ее из C++, как проверить регистры и как не нарушить соглашение вызова
Частые ошибки
Копируют NASM-код
MASM и NASM отличаются синтаксисом. Пример с section .text может не собраться в MASM без переделки
Путают x86 и x64
В x86 и x64 разные правила передачи аргументов
Не включили MASM для проекта
.asm-файл может просто лежать рядом, но не участвовать в сборке
Не объявили extern «C»
Без extern "C" C++ может изменить имя функции при линковке
Что почитать дальше по ассемблеру
Если нужен общий маршрут по теме, откройте рубрику ассемблеру. Для соседних задач пригодятся эти разборы:
- Как писать на ассемблере в Visual Studio
- Как запустить ассемблер в Visual Studio
- Как начать программировать на ассемблере
- Как программировать Arduino на ассемблере
Как проверить результат на практике
Для ассемблера важно сначала понять, под какую среду написан пример: DOSBox/TASM, Linux x64/NASM, Visual Studio/MASM или микроконтроллер. Один и тот же смысл может записываться разным синтаксисом, поэтому не переносите команды между средами вслепую. Создайте отдельную папку для примера, сохраните файл с расширением .asm, выполните сборку именно тем инструментом, который указан в уроке, и сравните вывод или состояние регистров с ожидаемым результатом
Если пример не собирается, читайте первую ошибку ассемблера: обычно она указывает на строку, неизвестную инструкцию, неверную метку, неправильную секцию или конфликт синтаксиса. Исправляйте одну ошибку за раз. В ассемблере это особенно важно, потому что маленькая опечатка в метке, регистре или размере операнда может полностью изменить поведение программы