Русские документы
Ежедневные компьютерные новости RSS rusdoc.ru  Найти :
Новости
Последние поступления
Книжный магазин
  Hardware:
Видеоустройства
Системные платы
Процессоры
Мобильные устройства
Аудиосистема
Охлаждение системы
Накопители информации
КПК и ноутбуки
Телефоны и связь
Периферия
Система
Сети
Разные устройства
 
  Programming:
Web-разработка
Языки программирования
Технологии и теория
Разработка игр
Программная инженерия
 
  Software:
Операционные системы
Windows 7
Базы данных
Обзоры программ
Графика и дизайн
   
  Life:
Компьютерная жизнь
Разные материалы
   
Партнеры
Публикация
Правовая информация
Реклама на сайте
Обратная связь
Экспорт в RSS Экспорт в RSS2.0
    Читать в Яндекс.Ленте



ASM + x64 + VS.NET 2005 = ERROR ?!

Раздел: Programming / .NET Framework @ 16.01.2008 | Ключевые слова: VS.NET 2005 Assembler error версия для печати

Автор: ACWares
Источник: CodeNet

ASM + x64 + VS.NET 2005 = ERROR ?!

Автор: ACWares

Здравствуйте, уважаемые любители (и профессионалы) низкоуровневого программирования. В этой статье рассмотрим проблему, которая, так сказать, образовалась "на ровном месте". Виновник - "всеми любимая" корпорация Microsoft. Заключается она в нежелании среды Visual Studio .NET компилировать ассемблерный код в 64-разрядном режиме. Но что делать, если требуется реализовать блок кода, который должен работать максимально быстро? Без использования ассемблера (ассемблерных вставок) здесь никак не обойтись. Конечно, можно попытаться оптимизировать код, но то, что этот код на высокоуровневом языке не будет "выжимать все соки из процессора", можно заявить однозначно.

В большинстве случаев программы на чистом ассемблере пишутся довольно редко, поэтому будем рассматривать ситуацию в ключе "пользовательский интерфейс - на языке высокого уровня, ядро - на языке ассемблера". Не будем выдумывать чего-то сложного, а остановимся на традиционной задаче - сумма двух чисел. Работать будем в среде VS.NET 2005. Необходимо отметить, что если Вы не хотите иметь дополнительных трудностей с отладкой программ, то у Вас так же должна быть установлена 64-разрядная ОС. Например, Windows XP x64-Edition или Windows Server 2003.

Принципиально задача будет выглядеть так: программа, управляющая часть (интерфейс) которой будет написана на C++, будет использовать функцию исполнительной части (ядра), написанного на языке ассемблера (MASM) и реализованного в виде DLL-модуля, для вычисления суммы 2 чисел.

Приступим. Сначала напишем DLL-модуль. Для этого нам понадобится MASM-компилятор. Находится он в одной из папок VS.NET 2005, а именно: :\Microsoft Visual Studio 8\VC\bin\amd64. Требуется в переменную окружения Path (Control Panel a System a Advanced a Environment Variables a System Variables) добавить этот путь. Там система и найдет файлы, необходимые для компиляции программы (ML64, LINK и некоторые другие).

Ассемблерный исходник будет выглядеть примерно так (kernel.asm):

 

.CODE

 

DllMain     PROC

      mov   rax,1

      ret

DllMain     ENDP

 

Sum   PROC

      mov         rax, rcx

      add         rax, rdx

      ret

Sum   ENDP

 

END 

Как и в любой DLL здесь есть функция DllMain, которая у нас всегда будет возвращать истину, и функция вычисления суммы (напомню, что компилятор C++ всегда ждет целочисленный результат выполнения функции в регистре-аккумуляторе). Для создания DLL-модуля необходим еще одни файл - файл с описанием экспортируемых функций - DEF-файл. Его содержимое будет выглядеть следующим образом (kernel.def):

LIBRARY           kernel

EXPORTS           Sum   @1

С исходными кодами закончили. Напишем пакетный файл для компиляции (Назовем его COMPILE.BAT, хотя это не принципиально):

ml64 kernel.asm /link /OUT:"kernel.dll" /DLL

/entry:DllMain /DEF:kernel.def /SUBSYSTEM:CONSOLE

Данной строкой запускаем компилятор ML64, компилируем kernel.asm. /link - запускаем компоновщик со следующими параметрами: /OUT:kernel.dll - выходной файл kernel.dll; /DLL - указывает на то, что должен быть создан DLL-модуль, /entry:DllMain - точка входа - функция DllMain, /DEF - def-файл kernel.def.

По первой части все. Запускаем файл COMPILE.BAT. Если все было сделано без ошибок, то появится несколько файлов. Из них нам нужен только один - kernel.dll.

Приступаем к созданию управляющего кода. Создадим консольное приложение Visual C++, назовем его test_x64. Так же необходимо скопировать файл kernel.dll в директорию проекта. Отредактируем файл test_x64.cpp, чтобы он принял следующий вид:

 

#include "stdafx.h"

#include #include #include  

using namespace std;

 

//Функция Sum будет иметь 2 целочисленных, возвращать она будет целое число

typedef __int64 (*pSum)(__int64, __int64);

 

int _tmain(int argc, _TCHAR* argv[])

{

      //Переменные для суммы

      __int64     a, b, r = 0;

 

      //Адрес DLL-модуля

      HMODULE hModule;

      //Адрес фунцкии вычисления адреса

      pSum Sum;

 

      //Загрузка DLL в адресное пространство процесса

      hModule = LoadLibraryA("kernel.dll");

      //Получения адреса функции с именем Sum

      Sum = (pSum)GetProcAddress(hModule, "Sum");

 

      cout << "A = ";

      cin >> a;

      cout << "B = ";

      cin >> b;

 

      //Вычислени суммы

      r = Sum(a, b);

 

      cout << "Result = " << r << endl;

            

      //Выгрузка DLL

      FreeLibrary(hModule);

 

      getch();

 

      return 0;

} 

Исходный код готов. Остался последний момент. Необходимо сообщить компилятору, что мы хотим получить 64-раздяное приложение. Делается это так. Открываем свойства проекта Solution Explorer a test_x64 a Properties. Вызываем менеджер конфигураций нажатием кнопки . В раскрывающемся списке выбираем . В первом раскрывающемся списке выбираем . (Если у вас нет этой записи, то это значит, что при установке VS.NET вы не указали компонент для компиляции программ под 64 разряда (находится в папке компонентов, относящихся к Visual C++) - придется установить этот компонент). Нажимаем OK. В списке проектов напротив test_x64 в поле Platform должно установиться x64. Нажимаем Close, тем самым вернувшись в окно свойств проекта. Далее необходимо отредактировать предпроцессорные директивы: в поле Configuration Properties a C/C++ a Preprocessor a Preprocessor Definitions изменим _WIN32 на _WIN64. Так же проверьте, что в Configuration Properties a Linker a Advanced a Target Machine выбран ключ /MACHINE:X64. Нажмите OK. Все, теперь все должно заработать.

В заключении отметим: статья кратко описывает весь процесс создания работающей программы, поэтому, если что-то (что вполне возможно) не получается, то можно скачать готовый пример. Находится он по следующему адресу: SampleX64.zip. Многие аспекты были рассмотрены очень кратко (например, установка компонентов для компиляции по 64 разряда), а объяснение некоторых - вообще опущено: что за регистры rax, rdx, rcx? Почему при выходе из функций не чистится стек? Откуда функция Sum берет параметры? Все это сделано для того, чтобы рассмотреть проблему <в чистом виде>. Т.е. предполагалось, что читатель уже хорошо ориентируется в программировании на языке ассемблера и знаком с программной структурой 64-разрядных процессоров. Если же это не так, то автор, по мере возможности, ответит на любые возникшие (даже косвенно относящиеся к данным темам) вопросы.

Это интересно:








версия для печатиРаспечатать статью


Вернуться в раздел: Programming / .NET Framework


Реклама:
Читать наc на:

Add to Google
Читать в Яндекс.Ленте






Rambler's Top100
© Copyright 1998-2012 Александр Томов. All rights reserved.