Assembler вместе с C++ в Visual Studio 2013

от автора

Идея этой статьи отнюдь не новая, но, поскольку мне пришлось потратить два дня на разбор всех ошибок компиляции и линковки, а также поиск ответов на свои вопросы, решил, что читатели Хабра заслуживают на экономию времени. Тех, кто желает быстро узнать, как использовать одновременно *.asm и *.cpp файлы в проекте, как вызывать методы C++ из ассемблера и наоборот, прошу пожаловать под кат.

Предисловие

Началось все с прочтения мной публикации «Ассемблер для Windows используя Visual Studio» (отсюда и почти идентичный код). Там рассмотрено использование Visual Studio 2005, а для 2013-й студии процесс похожий, но есть несколько отличий, которые заставят неподготовленного пользователя долго искать решения всех проблем со сборкой.

Содержание

  1. TL;DR
  2. Создание проекта
  3. Настройка подсветки синтаксиса
  4. Тонкости вызова методов между С++ и Asm
  5. Приложение

TL;DR

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

Создание проекта

Иллюстрированная версия

Включаем Visual Studio, выбираем File -> New -> Project…:

image

Выбираем шаблон Win32 Console Application, кликаем ОК:

image

Жмем Next:

image

Ставим галочку напротив Empty project и жмем Finish:

image

Создаем исходники. Для этого делаем правый клик на Source Files, выбираем Add -> New Item…:

image

Выбираем C++ File и жмем Add:

image

Аналогично, создаем *.asm файл (просто меняем расширение в поле Name):

image

Важно: имена файлов должны быть разными (не учитывая расширение), иначе при создании файлов *.obj возникнет проблема перезаписи одного обьектного файла другим.

Теперь настройки. Делаем правый клик на проекте, выбираем Build Dependencies -> Build Customizations…

image

Ставим галочку напротив masm и жмем ОК:

image

Делаем правый клик на файле *.asm, выбираем Properties…:

image

В поле Item Type выбираем Microsoft Macro Assembler и жмем ОК:

image

Выбираем Project -> Properties…:

image

Выбираем Configuration Properties -> Microsoft Macro Assembler -> Listing File. В поле Assembled Code Listing File вводим $(ProjectName).lst:

image

Выбираем Configuration Properties -> Linker -> Advanced. В поле Image Has Safe Exception Handlers выбираем значение No. Жмем ОК:

image

На этом этапе проект можно считать созданным. Написание кода рассмотрено в секции Тонкости вызова методов между С++ и Asm.

Только текст

Включаем Visual Studio, выбираем File -> New -> Project….

Выбираем шаблон Win32 Console Application, кликаем ОК.

Жмем Next.

Ставим галочку напротив Empty project и жмем Finish.

Создаем исходники. Для этого делаем правый клик на Source Files, выбираем Add -> New Item….

Выбираем C++ File и жмем Add.

Аналогично, создаем *.asm файл (просто меняем расширение в поле Name).

Важно: имена файлов должны быть разными(не учитывая расширение), иначе при создании файлов *.obj возникнет проблема перезаписи одного объектного файла другим.

Теперь настройки. Делаем правый клик на проекте, выбираем Build Dependencies -> Build Customizations…

Ставим галочку напротив masm и жмем ОК.

Делаем правый клик на файле *.asm, выбираем Properties…

В поле Item Type выбираем Microsoft Macro Assembler и жмем ОК.

Выбираем Project -> Properties…

Выбираем Configuration Properties -> Microsoft Macro Assembler -> Listing File. В поле Assembled Code Listing File вводим $(ProjectName).lst.

Выбираем Configuration Properties -> Linker -> Advanced. В поле Image Has Safe Exception Handlers выбираем значение No. Жмем ОК.

На этом этапе проект можно считать созданным. Написание кода рассмотрено в секции Тонкости вызова методов между С++ и Asm.

Настройка подсветки синтаксиса

Существует аддон для Visual Studio — asmHighlighter, однако на момент написания статьи версии для VS2013 не существовало. Однако, просмотрев раздел Discussions, я нашел сообщение пользователя Trass3r, который, к счастью, поделился репозиторием с версией аддона для VS2013. После установки Visual Studio SDK мне удалось собрать проект и теперь *.vsix пакет есть в свободном доступе.

Тонкости вызова методов между С++ и Asm

Для того, чтоб избежать ошибок компиляции и/или связывания нужно помнить следующее:

  1. Если надо вызывать из ассемблера библиотечные методы, достаточно в начале секции кода указать, какие именно методы мы собираемся использовать.
    EXTRN  printf : proc ;we'll use printf 

    Далее можно просто использовать call:

    ;printf(ebx,eax) push eax; push ebx call printf add esp, 8 ;pop x2 
  2. Если же надо вызывать пользовательские методы, то кроме п.1 надо еще писать extern «C» перед определением метода.
    extern "C" void* readName() { 	char* name = (char*)calloc(1, 255); 	scanf("%s", name); 	while (getchar() != '\n'); 	return name; } 

    Соответственно, в *.asm файле:

    EXTRN  readName : proc ;and void* readName() 

    и

    call readName ;eax = readName() 

  3. В случае использования Asm-методов в C++ достаточно лишь указать прототип:
    extern "C" { 	void sayHello(); } 

    Данный прототип соответствует такому объявлению Asm-метода:

    sayHello PROC  call readName ;eax = readName() lea ebx, helloFormat ;ebx = &helloFormat  ;printf(ebx,eax) push eax push ebx call printf add esp, 8 ;pop x2  retn  sayHello ENDP 

Собственно, полный исходный код примера:

Source.cpp

#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h>  extern "C" { 	void sayHello(); }  void main() { 	printf("Hello, what is your name?\n"); 	sayHello(); 	while (getchar() != '\n'); } extern "C" void* readName() { 	char* name = (char*)calloc(1, 255); 	scanf("%s", name); 	while (getchar() != '\n'); 	return name; } 

AsmSource.asm

.686 .MODEL FLAT, C .STACK .DATA ;-----------Local data------------------------------ helloFormat BYTE "Hello, %s!", 10, 13, 0 .CODE ;-----------External usage-------------------------- EXTRN  printf : proc;// we'll use printf EXTRN  readName : proc;//and void* readName() ;-----------Function definitions-------------------- sayHello PROC  call readName; eax = readName() lea ebx, helloFormat; ebx = &helloFormat  ;printf(ebx,eax) push eax push ebx call printf add esp, 8;pop x2  retn  sayHello ENDP  END 

Приложение

Готовый шаблон проекта можно найти здесь.
Пакет для подсветки asm синтаксиса можно найти здесь.

ссылка на оригинал статьи http://habrahabr.ru/post/252647/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *