Связь ассемблера с языками высокого уровня
Оптимизация с использованием языка низкого уровня ассемблера. Его связь с языками высокого уровня. Отдельно компилируемые модули. Разработка программных модулей на ассемблере с использованием компиляторов TASM5.0 фирмы Borlandи MASM6.14 фирмы Microsoft.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | курсовая работа |
Язык | русский |
Дата добавления | 18.05.2014 |
Размер файла | 405,5 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Размещено на http://www.allbest.ru
Размещено на http://www.allbest.ru
Оглавление
Оптимизация приложений при помощи ассемблера
Оптимизация с использованием языка низкого уровня ассемблера
Связь ассемблера с языками высокого уровня
Отдельно компилируемые модули
Встроенный ассемблер
Оптимизация приложений при помощи ассемблера
Большинство разработчиков понимает, что в условиях жесткой конкуренции вопрос производительности является важнейшим условием успеха или неудачи программы на рынке программных продуктов. Без серьезной работы над улучшением производительности программного кода нельзя обеспечить конкурентоспособность приложения. Хотя все осознают необходимость и важность процесса оптимизации программного обеспечения, эта тема до сих пор является противоречивой и дискуссионной. Все споры вокруг этого процесса в основном затрагивают один вопрос: так ли уж необходимо программисту заниматься ручной оптимизацией своего приложения, если для этого есть готовые аппаратно-программные средства?
Часть программистов считает, что улучшить производительность работы приложения без использования средств отладки самого компилятора нельзя, тем более что все современные компиляторы имеют встроенные(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выглядит так:
tasm32 /ml<имя_файла.asm><имя_файла.obj>
Если используется MASM, командная строка для компилятора будет выглядеть следующим образом:
ml/с /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 или
MyProc 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:
stpas.pas
unitstpas;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
I1Edit: TEdit;
Label1: TLabel;
I2Edit: TEdit;
Label2: TLabel;
subResult: TEdit;
Label3: TLabel;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{$L subtwo.obj}
functionsubtwo(i1:Integer; i2:Integer):Integer;stdcall;external;
procedure TForm1.Button1Click(Sender: TObject);
var
I1, I2: Integer;
begin
I1:= StrToInt(I1Edit.Text);
I2:= StrToInt(I2Edit.Text);
subResult.Text:= IntToStr(subtwo(I1, I2));
//
end;
end.
subtwo.asm
.386
.model flat
publicsubtwo
.data
.code
subtwoproc
pushEBP
movEBP, ESP
movEAX, DWORD PTR [EBP+8]
subEAX, DWORD PTR [EBP+12]
popEBP
ret8
subtwoendp
end
Скриншот:
Microsoft Visual C++ . Net:
SUBSTRACTION 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"
extern "C" int _stdcallsubtwo(int i1, int i2);
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CAboutDlg dialog used for App About
classCAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
voidCAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// CSUBSTRACTIONTWOINTSINCNETDlg dialog
CSUBSTRACTIONTWOINTSINCNETDlg::CSUBSTRACTIONTWOINTSINCNETDlg(CWnd* pParent /*=NULL*/)
: CDialog(CSUBSTRACTIONTWOINTSINCNETDlg::IDD, pParent)
, I1(0)
, I2(0)
, iSubResult(0)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
voidCSUBSTRACTIONTWOINTSINCNETDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT1, I1);
DDX_Text(pDX, IDC_EDIT2, I2);
DDX_Text(pDX, IDC_EDIT3, iSubResult);
}
BEGIN_MESSAGE_MAP(CSUBSTRACTIONTWOINTSINCNETDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1)
END_MESSAGE_MAP()
// CSUBSTRACTIONTWOINTSINCNETDlg message handlers
BOOL CSUBSTRACTIONTWOINTSINCNETDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CStringstrAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->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
SetIcon(m_hIcon, TRUE);// Set big icon
SetIcon(m_hIcon, FALSE);// Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
voidCSUBSTRACTIONTWOINTSINCNETDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID& 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlgdlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::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.
voidCSUBSTRACTIONTWOINTSINCNETDlg::OnPaint()
{
if (IsIconic())
{
CPaintDCdc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
intcxIcon = GetSystemMetrics(SM_CXICON);
intcyIcon = GetSystemMetrics(SM_CYICON);
CRectrect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CSUBSTRACTIONTWOINTSINCNETDlg::OnQueryDragIcon()
{
returnstatic_cast<HCURSOR>(m_hIcon);
}
voidCSUBSTRACTIONTWOINTSINCNETDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);
iSubResult = subtwo(I1, I2);
UpdateData(FALSE);
}
subtwo.asm
.386
.model flat
public _subtwo@8
.data
.code
_subtwo@8 proc
pushEBP
movEBP, ESP
movEAX, DWORD PTR [EBP+8]
subEAX, DWORD PTR [EBP+12]
popEBP
ret8
_subtwo@8 endp
end
Найти максимальное значение в массиве целых чисел (передача параметров через стек, по ссылке).
Delphi 7:
fmaxpas.pas
unitfmaxpas;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
Edit2: TEdit;
Label1: TLabel;
Label2: TLabel;
procedure Button1Click(Sender: TObject);
procedureFormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
I1:array [1..12] of integer = (585,1751,-27,-76,312, 93, 5, -1, 57, 22,-5, 997);
SI1: Integer;
pMax: PInteger;
Max: Integer;
implementation
{$R *.dfm}
{$L maxint.obj}
functionmaxint(PI1:PInteger;SI1:Integer):PInteger;stdcall;external;
procedure TForm1.Button1Click(Sender: TObject);
begin
pMax:= maxint(@I1,SI1);
Max:=pMax^;
Edit2.Text:= IntToStr(Max);
end;
procedure TForm1.FormCreate(Sender: TObject);
var
Cnt:Integer;
begin
SI1:= SizeOf(I1) div 4;
forCnt:= 1 to SI1 do
Edit1.Text:= Edit1.Text + ' ' + IntToStr(I1[Cnt]);
end;
end.
maxint.asm
.386
.model flat
publicmaxint
.data
.code
maxintproc
pushESI
pushEBP
movEBP, ESP
movEDX, DWORD PTR [EBP+16] ; first.parm - right - size
movESI, DWORD PTR [EBP+12] ; sec.parm - left - address of array
next_cmp:
movEAX, DWORD PTR [ESI]
cmpEAX, DWORD PTR [ESI+4]
jledec_cnt
xchgEAX, DWORD PTR [ESI+4]
dec_cnt:
decEDX
cmpEDX, 0
jefin
addESI, 4
jmpnext_cmp
fin:
movEAX, ESI
;
popEBP
popESI
ret8
maxintendp
end
Microsoft Visual C++ . Net:
Find Max Integer in ArrayDlg.cpp
#include "stdafx.h"
#include "Find Max Integer in Array.h"
#include "Find Max Integer in ArrayDlg.h"
extern "C" int* _stdcallmaxval(int *pi1, int si1);
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CAboutDlg dialog used for App About
classCAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
voidCAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// CFindMaxIntegerinArrayDlg dialog
CFindMaxIntegerinArrayDlg::CFindMaxIntegerinArrayDlg(CWnd* pParent /*=NULL*/)
: CDialog(CFindMaxIntegerinArrayDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
voidCFindMaxIntegerinArrayDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CFindMaxIntegerinArrayDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
//ON_WM_CREATE()
//ON_WM_ACTIVATE()
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
// CFindMaxIntegerinArrayDlg message handlers
BOOL CFindMaxIntegerinArrayDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CStringstrAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->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
SetIcon(m_hIcon, TRUE);// Set big icon
SetIcon(m_hIcon, FALSE);// Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
voidCFindMaxIntegerinArrayDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID& 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlgdlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::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.
voidCFindMaxIntegerinArrayDlg::OnPaint()
{
if (IsIconic())
{
CPaintDCdc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
intcxIcon = GetSystemMetrics(SM_CXICON);
intcyIcon = GetSystemMetrics(SM_CYICON);
CRectrect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CFindMaxIntegerinArrayDlg::OnQueryDragIcon()
{
returnstatic_cast<HCURSOR>(m_hIcon);
}
voidCFindMaxIntegerinArrayDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
int i1[10] = {674, 7, 90, -34, 2, -596, -45, 76, -12, 64};
charbuf[8];
CClientDCdc(this);
RECT rect;
GetClientRect(&rect);
for (intcnt = 0;cnt <sizeof(i1)/4;cnt++)
{
dc.TextOut((rect.right - rect.left)/30 + cnt*45 , (rect.bottom - rect.top )/ 4 , itoa(i1[cnt],buf,10));
};
intires = *maxval(i1, sizeof(i1)/4);
dc.TextOut((rect.right - rect.left)/2 - 40 , (rect.bottom - rect.top )/2 + 30 , itoa(ires, buf,10));
CDialog::OnLButtonDown(nFlags, point);
}
maxval.asm
.386
.model flat
public _maxval@8
.data
MaxVal DD 0
.code
_maxval@8 proc
pushESI
pushEBP
movEBP, ESP
movECX, DWORD PTR [EBP+16]
decECX
movESI, DWORD PTR [EBP+12]
movEAX, [ESI]
next_cmp:
cmpEAX, [ESI+4]
jggo_loop
movEAX, [ESI+4]
go_loop:
addESI, 4
loopnext_cmp
movDWORD PTR MaxVal, EAX
movEAX, OFFSET MaxVal
popEBP
popESI
ret8
_maxval@8 endp
end
Встроенный ассемблер
Найти сумму двух целых чисел:
basm1pas.pas
unit basm1pas;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
Label1: TLabel;
Edit2: TEdit;
Edit3: TEdit;
Label2: TLabel;
Label3: TLabel;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
I1, I2: Integer;
implementation
{$R *.dfm}
functionAddTwo(i1, i2:PInteger):PInteger;
var
ires:Integer;
begin
asm
push ESI
mov EAX, dwordptr i1
lea ESI, dwordptrires
mov EAX, [EAX]
mov ECX, dwordptr i2
add EAX, [ECX]
movdwordptr [ESI], EAX
mov @Result, ESI
pop ESI
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
I1:= StrToInt(Edit1.Text);
I2:= StrToInt(Edit2.Text);
Edit3.Text:= IntToStr(AddTwo(@I1, @I2)^);
end;
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
classCAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
voidCAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// CSummaofRealsDlg dialog
CSummaofRealsDlg::CSummaofRealsDlg(CWnd* pParent /*=NULL*/)
: CDialog(CSummaofRealsDlg::IDD, pParent)
, s_Array(_T(""))
, f_Summa(0)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
voidCSummaofRealsDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT1, s_Array);
DDX_Text(pDX, IDC_EDIT2, f_Summa);
}
BEGIN_MESSAGE_MAP(CSummaofRealsDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1)
END_MESSAGE_MAP()
// CSummaofRealsDlg message handlers
BOOL CSummaofRealsDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CStringstrAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->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
SetIcon(m_hIcon, TRUE);// Set big icon
SetIcon(m_hIcon, FALSE);// Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
voidCSummaofRealsDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID& 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlgdlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::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.
voidCSummaofRealsDlg::OnPaint()
{
if (IsIconic())
{
CPaintDCdc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
intcxIcon = GetSystemMetrics(SM_CXICON);
intcyIcon = GetSystemMetrics(SM_CYICON);
CRectrect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CSummaofRealsDlg::OnQueryDragIcon()
{
returnstatic_cast<HCURSOR>(m_hIcon);
}
float* CSummaofRealsDlg::sumReals(float* farray, int lf)
{
floatfsum;
_asm {
mov ESI, farray
mov ECX, lf
dec ECX
finit
fldz
fld [ESI]
next:
add ESI, 4
fadd [ESI]
loop next
fstpfsum
fwait
lea EAX, fsum
};
}
voidCSummaofRealsDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
floatfarray[] = {2.4, 5.9, -4.12, 3.12, -8.45};
intfsize = sizeof(farray)/4;
//
CStringstmp;
//
UpdateData(TRUE);
stmp.Empty;
for (intcnt = 0; cnt<fsize; cnt++)
{
stmp.Format("%.2f", farray[cnt]);
s_Array = s_Array + " " + stmp;
};
//
f_Summa = *sumReals(&farray[0], fsize);
UpdateData(FALSE);
}
Скриншот:
Размещено на Allbest.ru
Подобные документы
Структурные подразделения и отделы организации, ее технические программные средства. Разработка приложений обработки данных на ассемблере, языке программирования высокого уровня. Тестирование и оптимизация программных модулей. Разработка документации.
отчет по практике [175,0 K], добавлен 30.09.2022Взаимосвязь стадий процесса проектирования сложных программных систем. Создание компилятора подмножества языка высокого уровня (Pascal) на язык Ассемблера. Структура входных и выходных данных, алгоритмы их обработки. Рабочая документация программы.
курсовая работа [256,7 K], добавлен 27.07.2014Разработка комплекса алгоритмов. Кодирование и компиляция. Тестирование, отладка, испытание и сдача программы. Минимальные системные требования для использования Delphi 7. Написание программы с использованием инструментального языка высокого уровня.
курсовая работа [2,7 M], добавлен 21.02.2011Особенности ассемблера - машинно-ориентированного языка низкого уровня, применяемого для создания простых приложений. Связывание программ на разных языках. Типичный формат записи команд, инструкции и директивы языка ассемблера. Разработка игры "Змейка".
курсовая работа [215,0 K], добавлен 20.07.2014Создание программы с использованием принципов объектно-ориентированного программирования на языке высокого уровня С# средствами Microsoft Visual Studio 2010. Построение алгоритма реализации. Определение математического аппарата, применение его в задаче.
курсовая работа [500,4 K], добавлен 13.01.2015Методы грамматического разбора при разработке учебного транслятора. Проектирование лексического анализатора и магазинного автомата. Программная реализация синтаксического анализатора текстового языка высокого уровня. Разработка модуля интерпретации.
курсовая работа [697,2 K], добавлен 06.01.2013Построение компилятора с языка высокого уровня как одного из элементов системы программирования. Разработка компилятора ассемблера, модификация базы данных исходного макета. Загрузчик, эмулятор, отладчик. Использование Flex и Bison для программирования.
курсовая работа [599,0 K], добавлен 04.11.2014Транслятор как программа или техническое средство, выполняющее трансляцию программы. Рассмотрение основных особенностей постройки лексического анализатора. Знакомство с этапами разработки транслятора с ограниченного подмножества языка высокого уровня.
курсовая работа [580,5 K], добавлен 06.08.2013Методы численного интегрирования. Характеристика основных составляющих структурного программирования. Решение задания на языке высокого уровня Паскаль. Построение графического решения задачи в пакете Matlab. Решение задания на языке высокого уровня C.
курсовая работа [381,7 K], добавлен 10.05.2018Программная реализация настольного приложения с использованием языка программирования C#. Проектирование и структура пользовательского интерфейса, требования к нему и оценка функциональности. Разработка руководства пользователя и его использование.
курсовая работа [297,6 K], добавлен 10.03.2015