Функции, файлы, консоль, связь с C++ в MASM презентация

Содержание

Упрощаем программирование в MASM. Функции. Функции возвращают значение в регистр еах. Выглядит это примерно так: .data? hResult dd ? call/invoke SomeFunc mov hResult,eax В Си аналогичный код выглядит проще: HANDLE

Слайд 1ЭВМ и Периферийные устройства лекция 10


Слайд 2Упрощаем программирование в MASM. Функции.
Функции возвращают значение в регистр еах. Выглядит

это примерно так:

.data? hResult dd ? call/invoke SomeFunc mov hResult,eax

В Си аналогичный код выглядит проще:

HANDLE hResult; hResult = SomeFunc();

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

mov hResult,FUNC(SomeFunc)
;(переменную hResult нужно объявлять)


Слайд 3Упрощаем программирование в MASM. Файлы.
На чистом Асме, точнее на WinApi, ввод/вывод

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

mov hFile, fcreate("test.log")

Узнать размер файла:

mov flen, fsize(hFile)

Записать туда данные:

mov bwritten, fwrite(hFile,buffer,bcnt);хендл,адрес буфера с данными, к-тво ;байт для записи


Слайд 4Упрощаем программирование в MASM. Файлы.
А вот пример функции, которая откроет файл,

запишет туда данные, и закроет его:

invoke write_disk_file, chr$("file.txt"),addr lpData,fl;имя, буфер, к-тво байт для ;записи


Слайд 5Упрощаем программирование в MASM. Консоль.
Намного проще работать с консолью - если

на чистом WinApi нужно открыть дескриптор на запись, вызвать функции с несколькими параметрами, то с помощью макроссов можно просто:

invoke StdOut,chr$("console")

Или даже так:

print "console"

Естественно, никакого волшебства тут нет, в основе всего этого лежит тот жe WinApi.


Слайд 6Как связать C++ и Assembler под Windows
Существует 3 способа:
Разместить ассемблерный код

в отдельном файле *.asm. Сгенерировать ассемблерный *.obj файл и связать его с *.cpp файлом (С++);

Разместить ассемблерный код в отдельном файле. Сгенерировать *.dll из ассемблерного файла и вызывать функции из неё в C++ или другим языком высокого уровня;

Использовать inline assembler, позволяющий делать вставки ассемблерного кода в высокоуровневом языке.

Слайд 71) Разместить ассемблерный код в отдельном файле. Сгенерировать ассемблерный *.obj файл

и связать его с *.cpp файлом (С++)

Особенности:
Создаётся отдельный .ASM файл, процедуры которого вызываются из высокоуровневого С++ кода.

Преимущества:
Относительно простой способ;

Недостатки:
Ассемблерный код будет размещён всегда отдельном файле;
Необходимость прописывать прототипы ASM функций в С++ коде


Слайд 81) Разместить ассемблерный код в отдельном файле. Сгенерировать ассемблерный *.obj файл

и связать его с *.cpp файлом (С++)

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

(ASM)
EXTRN printf : proc ;we'll use printf

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

(ASM)
;printf(ebx,eax)
push eax;
push ebx
call printf
add esp, 8 ;pop x2


Слайд 91) Разместить ассемблерный код в отдельном файле. Сгенерировать ассемблерный *.obj файл

и связать его с *.cpp файлом (С++)

Если же вы захотите использовать invoke (что удобнее и логичнее), то нужно прописать прототип

(ASM)
.data
helloFormat BYTE "Hello, %s!", 10, 13, 0
whatToPrint DWORD “PrintIt”

printf PROTO arg1:Ptr Byte, printlist: VARARG ; Мы используем Сишный printf с ;описанием прототипа

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

(ASM)
invoke printf, ADDR helloFormat, whatToPrint


Слайд 101) Разместить ассемблерный код в отдельном файле. Сгенерировать ассемблерный *.obj файл

и связать его с *.cpp файлом (С++)

Если вы хотите из Asm файла вызывать методы С++ то используется указанный ранее подход, но при этом в С++ файле у вызываемого метода вы должны сделать приписку extern "C"

(C++)
extern "C"
void* readName()
{
char* name = (char*)calloc(1, 255);
scanf("%s", name);
while (getchar() != '\n');
return name; //eax= name
}

(ASM)
invoke readName ; eax=name


Слайд 111) Разместить ассемблерный код в отдельном файле. Сгенерировать ассемблерный *.obj файл

и связать его с *.cpp файлом (С++)

Если вам нужно вызвать ASM методы из C++, то в С++ нужно прописать прототип:

(C++)
extern "C"
{
long calcSumm(long a, long * retAddr);
}

int _tmain(int argc, _TCHAR* argv[])
{
long retVar=1;
long res=calcSumm(31,&retVar);
}

(ASM)
calcSumm PROC a:DWORD,retAddr:DWORD

ret
calcSumm ENDP


Слайд 122) Сгенерировать *.dll из ассемблерного файла и вызывать функции из неё

в C++ или другим языком высокого уровня;

Особенности:
На основе ASM файла генерируется *.DLL, которая вызывается в языках высокого уровня.

Преимущества:
Универсальный способ, подходящий для связи многих языков;

Недостатки:
Ассемблерный код будет размещён в отдельном файле;
Необходимость приписывать вызов функций из DLL.


Слайд 132) Сгенерировать *.dll из ассемблерного файла и вызывать функции из неё

в C++ или другим языком высокого уровня;

Быстро создать шаблон DLL для MASM вы можете из редактора MASM32


Слайд 142) Сгенерировать *.dll из ассемблерного файла и вызывать функции из неё

в C++ или другим языком высокого уровня;

Далее нужную функцию или функции нужно просто вызвать из DLL средствами вашего языка программирования. Например так:

(C++)
include "stdafx.h"
#include
#pragma comment(lib,"..\\Debug\\MasmDLL.lib")
extern "C" void _stdcall TestProc1(char lpString[]);
int _tmain(int argc, _TCHAR* argv[])
{
char hello[] = "Hello World!";
TestProc1(hello);
printf("Press Enter To Exit...");
getchar();
return 0;
}



Слайд 153) Inline Assembler
Особенности:
Inline Assembler, то есть использование встроенного в язык высокого

уровня ассемблерного кода (или ассемблерных вставок, как их ещё называют).
Inline Assembler в Visual Studio использует синтаксис MASM.

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

Недостатки:
Встроенный код на языке ассемблера не поддерживает все макросы и директивы данных Microsoft Macro Assembler (MASM);
Программы со встроенным кодом на языке ассемблера не всегда можно перенести на другие аппаратные платформы. При разработке переносимой версии старайтесь не использовать встроенный код ассемблера;
64 битные приложения не поддерживаются.

Слайд 163) Inline Assembler
Ключевое слово __asm вызывает встроенный ассемблер и может использоваться

в любом месте, в котором может использоваться оператор С или С++.
Он не может отображаться самостоятельно. За ним должна следовать группа инструкций, заключенная в круглые скобки, либо, в крайнем случае, пустая пара круглых скобок. Термин "блок __asm" в этом разделе относится к любой инструкции или группе инструкций, в скобках или без них.

(С++)
__asm push ebp
__asm mov ebp, esp
__asm sub esp, __LOCAL_SIZE

Кроме того, можно поставить __asm перед каждой инструкцией по сборке.

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

(С++)
__asm push ebp __asm mov ebp, esp __asm sub esp, __LOCAL_SIZE

(С++)
__asm{…}


Слайд 173) Inline Assembler. Вызов С функций
В этом примере в стек помещаются

указатели на строки world, hello и format (в этом порядке), затем вызывается процедура printf.

(C++)
int _tmain(int argc, _TCHAR* argv[])
{
char format[] = "%s %s\n";
char hello[6] = "Hello";
char world[] = "World";
__asm //Ассемблерная вставка
{
lea eax,world // eax = адрес earth
push eax // поместить eax в вершину стека
lea eax,hello // eax = адрес hello
push eax
lea eax,format
push eax
call DWORD ptr printf
// или использя непрямой вызов
// mov eax, printf
// call eax
pop ebx // чистим стек
pop ebx
pop ebx

}
getchar();// ждем нажатие кнопки
return 0;
}


Слайд 183) Inline Assembler. Вызов С++ функций
Блок __asm может вызывать только глобальные

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

Кроме того, можно вызывать любые функции, которые объявлены с компоновкой extern "C". Благодаря этому блок __asm в программе C++ может вызывать функции библиотеки C, поскольку во всех стандартных файлах заголовков функции библиотеки объявляются с компоновкой extern "C".

Слайд 19Важно
Обычные компиляторы, работающие с высокоуровневым кодом (например MSBuild от Microsoft) сами

по себе неплохо оптимизируют код.

Далеко не всегда имеет смысл программировать что-либо именно на ассемблере. Это может не дать ощутимого эффекта.

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

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

Обратная связь

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

Email: Нажмите что бы посмотреть 

Что такое ThePresentation.ru?

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


Для правообладателей

Яндекс.Метрика