Связь ассемблера с языками высокого уровня

 

Оглавление


Оптимизация приложений при помощи ассемблера

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

Связь ассемблера с языками высокого уровня

Отдельно компилируемые модули

Встроенный ассемблер


Оптимизация приложений при помощи ассемблера


Большинство разработчиков понимает, что в условиях жесткой конкуренции вопрос производительности является важнейшим условием успеха или неудачи программы на рынке программных продуктов. Без серьезной работы над улучшением производительности программного кода нельзя обеспечить конкурентоспособность приложения. Хотя все осознают необходимость и важность процесса оптимизации программного обеспечения, эта тема до сих пор является противоречивой и дискуссионной. Все споры вокруг этого процесса в основном затрагивают один вопрос: так ли уж необходимо программисту заниматься ручной оптимизацией своего приложения, если для этого есть готовые аппаратно-программные средства?

Часть программистов считает, что улучшить производительность работы приложения без использования средств отладки самого компилятора нельзя, тем более что все современные компиляторы имеют встроенные(built-in) средства оптимизации программного кода. Можно полностью положиться на компилятор, который сгенерирует для вас оптимальный код, и вообще не заниматься улучшением качества программы. При этом в целом ряде случаев может и не понадобиться никаких доработок и улучшений. Например, при создании небольших офисных приложений или утилит тестирования сети оптимизация обычно не нужна.

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

Если программист разрабатывает программы, работающие в реальном времени, такие как драйверы устройств, системные службы или промышленные приложения, то без очень серьезной работы по ручной доводке кода до оптимальной производительности задача написания программы просто не будет выполнена. И дело здесь не в том, что средства разработки несовершенны и не обеспечивают того уровня оптимизации, какой от них требуется. Любая более или менее серьезная программа имеет столько взаимосвязанных параметров, что ни одно средство разработки не улучшит ее так, как это может сделать сам программист. Процесс оптимизации программ сродни скорее искусству, чем "чистому" программированию, и трудно поддается алгоритмизации.

Улучшение производительности программ - процесс обычно трудоемкий, занимающий значительную часть времени. Хочется отметить, что не существует единого критерия оптимизации. Более того, сам процесс оптимизации довольно противоречив. Например, если добиться уменьшения объема памяти, используемого программой, то за это придется расплатиться потерей быстродействия работы программы.

Ни одна программа не может быть одновременно сверхбыстрой, сверхмалой по размеру и полнофункциональной для пользователя.

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

Для многих офисных приложений очень важным показателем является удобство интерфейса пользователя и как можно более высокая функциональность. Например, для пользователя программы электронного телефонного справочника тот факт, что программа работает на 10% быстрее или медленнее, особого значения не имеет. Размер такой программы, в принципе, не критичен и также не имеет особого значения, т. к. объем современных жестких дисков достаточно большой, чтобы поместить десятки и даже сотни таких электронных справочников. Программе может быть необходимо десятки мегабайт оперативной памяти для работы - это тоже сейчас не проблема. Но вот возможность удобной манипуляции данными для пользователя будет очень важной.

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

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

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

Простейший способ заставить приложения работать быстрее - это повысить вычислительную мощь компьютера за счет установки более производительного процессора или увеличения объема памяти, т. е. сделать апгрейд (upgrade) аппаратной части. В этом случае проблема производительности будет решена сама собой.

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

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

Поэтому вряд ли стоит полагаться всерьез на решение проблем с программным обеспечением при помощи одной только закупки нового оборудования.

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

Оптимизация может проводиться по следующим направлениям:

тщательная проработка алгоритма разрабатываемой программы;

учет существующих аппаратных средств компьютера и использование их оптимальным образом;

использование средств языка высокого уровня той среды, в которой разрабатывается приложение;

использование языка низкого уровня ассемблера;

учет специфических особенностей процессора.

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


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


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

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

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


Связь ассемблера с языками высокого уровня


В основном программисты пишут на одном из двух языков высокого уровня: Pascalили C++. Современные средства быстрого проектирования с использованием C++ и Pascal, такие как MicrosoftVisualStudio.NET, BorlandC++ Builder 6 и BorlandDelphi 7, пользуются наибольшей популярностью среди программистов. Исходя из этого решено использовать для демонстрации основных принципов построения интерфейсов две среды программирования двух наиболее ярких представителей на рынке программных средств проектирования - MicrosoftVisualC++ .NETи BorlandDelphi 7.

Программные модули на ассемблере мы будем разрабатывать с использованием компиляторов TASM5.0 фирмы Borlandи MASM6.14 фирмы Microsoft.

В общем случае командная строка для компилятора TASMвыглядит так:/ml<имя_файла.asm><имя_файла.obj>

Если используется MASM, командная строка для компилятора будет выглядеть следующим образом:/с /Fo<имя_файла.obj><имя_файла.asm>

Никакие дополнительные опции компиляторов для получения файлов с расширением .OBJне нужны.

При решении этой задачи программист должен учитывать следующее:

правила согласования имен идентификаторов (переменных и процедур), помещенных в объектные файлы. Компилятор языка высокого уровня может изменять или нет оригинальные имена в объектном модуле, поэтому важно знать, происходит ли такое изменение и как;

модель памяти, используемую ассемблерным модулем(tiny, small, compact, medium, huge, large,flat);

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

нужно ли сохранять регистры в подпрограмме? Если да, то какие;

порядок передачи параметров вызываемой подпрограмме;

метод передачи параметров в подпрограмму (с использованием регистров, стека, разделяемой памяти);

способ передачи параметров в вызываемую подпрограмму (по значению или по ссылке);

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

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

Начнем с согласования имен идентификаторов:в языкеPascal все строчные буквы в именах внешних идентификаторов преобразуются в прописные. Компилятор C++ не изменяет регистра букв, но имена идентификаторов по этой причине считаются чувствительными к регистру. Кроме того, компилятор C++ перед всеми внешними именами помещает префикс в виде символа подчеркивания.

Следующий момент - модели памяти, используемые внешними подпрограммами. Для 32-разрядных приложений используется только одна модель памяти - flat. Она поддерживается как компилятором Pascal, так и C++. ассемблер язык программный модуль

Что касается параметров вызова внешних подпрограмм, то для 32-разрядных приложений параметры в вызываемую процедуру передаются одним из двух способов: либо по значению, либо по ссылке. При передаче параметра по значению в процедуру передается непосредственно сам 32-разрядный операнд, а при передаче по ссылке - адрес (тоже 32-разрядное значение) этого операнда.

Все параметры являются 32-разрядными. Понятия "ближняя ссылка" и "дальняя ссылка" не различаются! Все ссылки в адресном пространстве 32-разрядных приложений являются "ближними". Например, не имеет смысла объявлять подпрограммы как nearили far:

MyProc PROC NEAR илиPROC FAR

поскольку компилятор все равно интерпретирует все вызовы как ближние.

Для такой модели не существует отдельных сегментов данных и кода. Пространство адресов считается линейным, и в нем располагаются код и данные, которые используют 32-разрядные смещения, а вызовы процедур и функций считаются ближними. Такой режим работы обеспечивает высокую производительность 32- разрядных приложений, т. к. нет преобразования "сегмент-смещение" в абсолютные адреса. Кроме того, 32-разрядные приложения "не видят" друг друга и выполняются в изолированном от других приложений пространстве адресов. Это очень сильно отличает их от 16-разрядных приложений, где все программы могли "видеть" друга.

Параметры в вызываемую процедуру передаются через стек или через регистры. Все варианты передачи параметров через стек или регистры представлены в табл.1.


Таблица 1. Варианты передачи параметров

ДирективаПорядок передачи параметровОсвобождение стекаПередача параметров через регистрыregister, fastcall fastcallСлева направоПроцедураЕАХ, EDX, ЕСХpascalСлева направоПроцедураНетcdeclСправа налевоВызывающая программаНетstdcallСправа налевоПроцедураНетsafecallСправа налевоПроцедураНет

Порядок передачи параметров для каждой директивы указывает компилятору, каким образом параметры передаются в вызываемую процедуру. Для директив pascal, cdecl, stdcallи safecallпараметры передаются через стек, а при использовании директив registerили fastcall- через регистры.

Перед возвращением в основную программу необходимо восстановить указатель стека. Это относится кдирективам pascal, cdecl, stdcallиsafecall. Что касается применения тех или иных способов вызова внешних процедур, то здесь не существует однозначных рецептов. Если вы работаете с APIфункциями Windows, то для них стандартным способом вызова является stdcallили safecall. Директиву cdeclлучше использовать для вызова процедур и функций из программ, написанных в C++.

Наиболее быстрым способом передачи параметров является регистровый(register, или fastcall). Директива registerиспользуется в большинстве языков высокого уровня, но разработчики Microsoftрешили назвать ее по- другому, и в VisualC++ она определяется иначе - fastcall. Стек в этом случае не используется, поэтому мы получаем выигрыш по скорости выполнения подпрограммы.

Директива pascalиспользуется редко и только в целях обратной совместимости(backwardcompatibility).

Все подпрограммы возвращают результат (значение или адрес) в регистре ЕАХ.


Отдельно компилируемые модули


Разработаем программу на языке высокого уровня, вызывающую процедуру subtwo (передача параметров через стек, по значению).

Delphi 7:.pas;

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls;

TForm1 = class(TForm)

I1Edit: TEdit;

Label1: TLabel;

I2Edit: TEdit;

Label2: TLabel;: TEdit;

Label3: TLabel;

Button1: TButton;Button1Click(Sender: TObject);

{ Private declarations }

{ Public declarations };

Form1: TForm1;

{$R *.dfm}

{$L subtwo.obj}(i1:Integer; i2:Integer):Integer;stdcall;external;TForm1.Button1Click(Sender: TObject);

I1, I2: Integer;

I1:= StrToInt(I1Edit.Text);

I2:= StrToInt(I2Edit.Text);.Text:= IntToStr(subtwo(I1, I2));

//;..asm

.386

.model flat

.data

.code, ESP, DWORD PTR [EBP+8], DWORD PTR [EBP+12]

Скриншот:


Visual C++ . Net:TWO INTS IN C.NETDlg.cpp

#include "stdafx.h"

#include "SUBSTRACTION TWO INTS IN C.NET.h"

#include "SUBSTRACTION TWO INTS IN C.NETDlg.h""C" int _stdcallsubtwo(int i1, int i2);


#ifdef _DEBUG

#define new DEBUG_NEW

#endif

// CAboutDlg dialog used for App About: public CDialog

{:();

// Dialog Data{ IDD = IDD_ABOUTBOX };

protected:

virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support

// Implementation:_MESSAGE_MAP()

};::CAboutDlg() : CDialog(CAboutDlg::IDD)

{

}::DoDataExchange(CDataExchange* pDX)

{::DoDataExchange(pDX);

}_MESSAGE_MAP(CAboutDlg, CDialog)_MESSAGE_MAP()

// CSUBSTRACTIONTWOINTSINCNETDlg dialog::CSUBSTRACTIONTWOINTSINCNETDlg(CWnd* pParent /*=NULL*/)

: CDialog(CSUBSTRACTIONTWOINTSINCNETDlg::IDD, pParent)

, I1(0)

, I2(0)

, iSubResult(0)

{_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

}::DoDataExchange(CDataExchange* pDX)

{::DoDataExchange(pDX);_Text(pDX, IDC_EDIT1, I1);_Text(pDX, IDC_EDIT2, I2);_Text(pDX, IDC_EDIT3, iSubResult);

}_MESSAGE_MAP(CSUBSTRACTIONTWOINTSINCNETDlg, CDialog)_WM_SYSCOMMAND()_WM_PAINT()_WM_QUERYDRAGICON()

//}}AFX_MSG_MAP_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1)_MESSAGE_MAP()

// CSUBSTRACTIONTWOINTSINCNETDlg message handlersCSUBSTRACTIONTWOINTSINCNETDlg::OnInitDialog()

{::OnInitDialog();

// Add "About..." menu item to system menu.

// IDM_ABOUTBOX must be in the system command range.((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);(IDM_ABOUTBOX < 0xF000);* pSysMenu = GetSystemMenu(FALSE);(pSysMenu != NULL)

{;.LoadString(IDS_ABOUTBOX);(!strAboutMenu.IsEmpty())

{>AppendMenu(MF_SEPARATOR);>AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);

}

}

// Set the icon for this dialog. The framework does this automatically

// when the application's main window is not a dialog(m_hIcon, TRUE);// Set big icon(m_hIcon, FALSE);// Set small icon

// TODO: Add extra initialization hereTRUE; // return TRUE unless you set the focus to a control

}::OnSysCommand(UINT nID, LPARAM lParam)

{((nID& 0xFFF0) == IDM_ABOUTBOX)

{;.DoModal();

}

{::OnSysCommand(nID, lParam);

}

}

// If you add a minimize button to your dialog, you will need the code below

// to draw the icon. For MFC applications using the document/view model,

// this is automatically done for you by the framework.::OnPaint()

{(IsIconic())

{(this); // device context for painting(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

// Center icon in client rectangle= GetSystemMetrics(SM_CXICON);= GetSystemMetrics(SM_CYICON);;(&rect);x = (rect.Width() - cxIcon + 1) / 2;y = (rect.Height() - cyIcon + 1) / 2;

// Draw the icon.DrawIcon(x, y, m_hIcon);

}

{::OnPaint();

}

}

// The system calls this function to obtain the cursor to display while the user drags

// the minimized window.CSUBSTRACTIONTWOINTSINCNETDlg::OnQueryDragIcon()

{_cast<HCURSOR>(m_hIcon);

}::OnBnClickedButton1()

{

// TODO: Add your control notification handler code here(TRUE);= subtwo(I1, I2);(FALSE);

}.asm

.386

.model flat_subtwo@8

.data

.code

_subtwo@8 proc, ESP, DWORD PTR [EBP+8], DWORD PTR [EBP+12]

_subtwo@8 endp



Найти максимальное значение в массиве целых чисел (передача параметров через стек, по ссылке).

Delphi 7:.pas;

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls;

TForm1 = class(TForm)

Button1: TButton;

Edit1: TEdit;

Edit2: TEdit;

Label1: TLabel;

Label2: TLabel;Button1Click(Sender: TObject);(Sender: TObject);

{ Private declarations }

{ Public declarations };

Form1: TForm1;

I1:array [1..12] of integer = (585,1751,-27,-76,312, 93, 5, -1, 57, 22,-5, 997);

SI1: Integer;: PInteger;

Max: Integer;

{$R *.dfm}

{$L maxint.obj}(PI1:PInteger;SI1:Integer):PInteger;stdcall;external;TForm1.Button1Click(Sender: TObject);:= maxint(@I1,SI1);

Max:=pMax^;

Edit2.Text:= IntToStr(Max);;TForm1.FormCreate(Sender: TObject);:Integer;

SI1:= SizeOf(I1) div 4;:= 1 to SI1 do

Edit1.Text:= Edit1.Text + ' ' + IntToStr(I1[Cnt]);;..asm

.386

.model flat

.data

.code, ESP, DWORD PTR [EBP+16] ; first.parm - right - size , DWORD PTR [EBP+12] ; sec.parm - left - address of array_cmp: , DWORD PTR [ESI], DWORD PTR [ESI+4]_cnt, DWORD PTR [ESI+4]_cnt:, 0, 4_cmp:, ESI

;

maxintendp


Visual C++ . Net:Max Integer in ArrayDlg.cpp

#include "stdafx.h"

#include "Find Max Integer in Array.h"

#include "Find Max Integer in ArrayDlg.h""C" int* _stdcallmaxval(int *pi1, int si1);

#ifdef _DEBUG

#define new DEBUG_NEW

#endif

// CAboutDlg dialog used for App About: public CDialog

{:();

// Dialog Data{ IDD = IDD_ABOUTBOX };:void DoDataExchange(CDataExchange* pDX); // DDX/DDV support

// Implementation:_MESSAGE_MAP()

};::CAboutDlg() : CDialog(CAboutDlg::IDD)

{

}::DoDataExchange(CDataExchange* pDX)

{::DoDataExchange(pDX);

}_MESSAGE_MAP(CAboutDlg, CDialog)_MESSAGE_MAP()

// CFindMaxIntegerinArrayDlg dialog::CFindMaxIntegerinArrayDlg(CWnd* pParent /*=NULL*/)

: CDialog(CFindMaxIntegerinArrayDlg::IDD, pParent)

{_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

}::DoDataExchange(CDataExchange* pDX)

{::DoDataExchange(pDX);

}_MESSAGE_MAP(CFindMaxIntegerinArrayDlg, CDialog)_WM_SYSCOMMAND()_WM_PAINT()_WM_QUERYDRAGICON()

//}}AFX_MSG_MAP

//ON_WM_CREATE()

//ON_WM_ACTIVATE()_WM_LBUTTONDOWN()_MESSAGE_MAP()

// CFindMaxIntegerinArrayDlg message handlersCFindMaxIntegerinArrayDlg::OnInitDialog()

{::OnInitDialog();


// Add "About..." menu item to system menu.

// IDM_ABOUTBOX must be in the system command range.((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);(IDM_ABOUTBOX < 0xF000);* pSysMenu = GetSystemMenu(FALSE);(pSysMenu != NULL)

{;.LoadString(IDS_ABOUTBOX);(!strAboutMenu.IsEmpty())

{>AppendMenu(MF_SEPARATOR);>AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);

}

}

// Set the icon for this dialog. The framework does this automatically

// when the application's main window is not a dialog(m_hIcon, TRUE);// Set big icon(m_hIcon, FALSE);// Set small icon

// TODO: Add extra initialization hereTRUE; // return TRUE unless you set the focus to a control

}::OnSysCommand(UINT nID, LPARAM lParam)

{((nID& 0xFFF0) == IDM_ABOUTBOX)

{;.DoModal();

}

{::OnSysCommand(nID, lParam);

}

}

// If you add a minimize button to your dialog, you will need the code below

// to draw the icon. For MFC applications using the document/view model,

// this is automatically done for you by the framework.::OnPaint()

{(IsIconic())

{(this); // device context for painting(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

// Center icon in client rectangle= GetSystemMetrics(SM_CXICON);= GetSystemMetrics(SM_CYICON);;(&rect);x = (rect.Width() - cxIcon + 1) / 2;y = (rect.Height() - cyIcon + 1) / 2;

// Draw the icon.DrawIcon(x, y, m_hIcon);

}

{::OnPaint();

}

}

// The system calls this function to obtain the cursor to display while the user drags

// the minimized window.CFindMaxIntegerinArrayDlg::OnQueryDragIcon()

{_cast<HCURSOR>(m_hIcon);

}::OnLButtonDown(UINT nFlags, CPoint point)

{

// TODO: Add your message handler code here and/or call defaulti1[10] = {674, 7, 90, -34, 2, -596, -45, 76, -12, 64};[8];(this);rect;(&rect);(intcnt = 0;cnt <sizeof(i1)/4;cnt++)

{.TextOut((rect.right - rect.left)/30 + cnt*45 , (rect.bottom - rect.top )/ 4 , itoa(i1[cnt],buf,10));

};= *maxval(i1, sizeof(i1)/4);.TextOut((rect.right - rect.left)/2 - 40 , (rect.bottom - rect.top )/2 + 30 , itoa(ires, buf,10));

::OnLButtonDown(nFlags, point);

}.asm


.386

.model flat_maxval@8

.dataDD 0

.code

_maxval@8 proc, ESP, DWORD PTR [EBP+16], DWORD PTR [EBP+12], [ESI]_cmp: , [ESI+4]_loop, [ESI+4]_loop:, 4_cmpPTR MaxVal, EAX, OFFSET MaxVal

_maxval@8 endp



Встроенный ассемблер


Найти сумму двух целых чисел:

basm1pas.pasbasm1pas;

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls;

TForm1 = class(TForm)

Button1: TButton;

Edit1: TEdit;

Label1: TLabel;

Edit2: TEdit;

Edit3: TEdit;

Label2: TLabel;

Label3: TLabel;Button1Click(Sender: TObject);

{ Private declarations }

{ Public declarations };

Form1: TForm1;

I1, I2: Integer;

{$R *.dfm}(i1, i2:PInteger):PInteger;:Integer;ESIEAX, dwordptr i1ESI, dwordptriresEAX, [EAX]ECX, dwordptr i2EAX, [ECX][ESI], EAX@Result, ESIESI;;TForm1.Button1Click(Sender: TObject);

I1:= StrToInt(Edit1.Text);

I2:= StrToInt(Edit2.Text);

Edit3.Text:= IntToStr(AddTwo(@I1, @I2)^);

end;.

Скриншот:


Найти сумму элементов в массиве:

Summa of RealsDlg.cpp

#include "stdafx.h"

#include "Summa of Reals.h"

#include "Summa of RealsDlg.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#endif

// CAboutDlg dialog used for App About: public CDialog

{:();

// Dialog Data{ IDD = IDD_ABOUTBOX };:void DoDataExchange(CDataExchange* pDX); // DDX/DDV support

// Implementation:_MESSAGE_MAP()

};

::CAboutDlg() : CDialog(CAboutDlg::IDD)

{

}::DoDataExchange(CDataExchange* pDX)

{::DoDataExchange(pDX);

}_MESSAGE_MAP(CAboutDlg, CDialog)_MESSAGE_MAP()

// CSummaofRealsDlg dialog::CSummaofRealsDlg(CWnd* pParent /*=NULL*/)

: CDialog(CSummaofRealsDlg::IDD, pParent)

, s_Array(_T(""))

, f_Summa(0)

{_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

}::DoDataExchange(CDataExchange* pDX)

{::DoDataExchange(pDX);_Text(pDX, IDC_EDIT1, s_Array);_Text(pDX, IDC_EDIT2, f_Summa);

}_MESSAGE_MAP(CSummaofRealsDlg, CDialog)_WM_SYSCOMMAND()_WM_PAINT()_WM_QUERYDRAGICON()

//}}AFX_MSG_MAP_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1)_MESSAGE_MAP()

// CSummaofRealsDlg message handlersCSummaofRealsDlg::OnInitDialog()

{::OnInitDialog();

// Add "About..." menu item to system menu.

// IDM_ABOUTBOX must be in the system command range.((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);(IDM_ABOUTBOX < 0xF000);* pSysMenu = GetSystemMenu(FALSE);(pSysMenu != NULL)

{;.LoadString(IDS_ABOUTBOX);(!strAboutMenu.IsEmpty())

{>AppendMenu(MF_SEPARATOR);>AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);

}

}

// Set the icon for this dialog. The framework does this automatically

// when the application's main window is not a dialog(m_hIcon, TRUE);// Set big icon(m_hIcon, FALSE);// Set small icon

// TODO: Add extra initialization hereTRUE; // return TRUE unless you set the focus to a control

}::OnSysCommand(UINT nID, LPARAM lParam)

{((nID& 0xFFF0) == IDM_ABOUTBOX)

{;.DoModal();

}

{::OnSysCommand(nID, lParam);

}

}

// If you add a minimize button to your dialog, you will need the code below

// to draw the icon. For MFC applications using the document/view model,

// this is automatically done for you by the framework.::OnPaint()

{(IsIconic())

{(this); // device context for painting(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

// Center icon in client rectangle= GetSystemMetrics(SM_CXICON);= GetSystemMetrics(SM_CYICON);;(&rect);x = (rect.Width() - cxIcon + 1) / 2;y = (rect.Height() - cyIcon + 1) / 2;

// Draw the icon.DrawIcon(x, y, m_hIcon);

}

{::OnPaint();

}

}

// The system calls this function to obtain the cursor to display while the user drags

// the minimized window.CSummaofRealsDlg::OnQueryDragIcon()

{_cast<HCURSOR>(m_hIcon);

}* CSummaofRealsDlg::sumReals(float* farray, int lf)

{;

_asm {ESI, farrayECX, lfECX[ESI]:ESI, 4 [ESI]nextEAX, fsum

};

}::OnBnClickedButton1()

{

// TODO: Add your control notification handler code here[] = {2.4, 5.9, -4.12, 3.12, -8.45};= sizeof(farray)/4;

//;

//(TRUE);.Empty;(intcnt = 0; cnt<fsize; cnt++)

{.Format("%.2f", farray[cnt]);_Array = s_Array + " " + stmp;

};

//_Summa = *sumReals(&farray[0], fsize);

UpdateData(FALSE);

}

Скриншот:




Оглавление Оптимизация приложений при помощи ассемблера Оптимизация с использованием языка низкого уровня ассемблера Связь ассемблера с языками выс

Больше работ по теме:

КОНТАКТНЫЙ EMAIL: [email protected]

Скачать реферат © 2017 | Пользовательское соглашение

Скачать      Реферат

ПРОФЕССИОНАЛЬНАЯ ПОМОЩЬ СТУДЕНТАМ