Основание
системы счисления входных данных
|
Основание
системы счисления выходных данных
|
Функция
|
Набор
команд
|
16
|
16
|
|
Арифметический
сопроцессор
|
Введение
Цель курсовой работы: получить практические
навыки программирования диалоговых окон в MASM32, ознакомиться с набором команд
арифметического сопроцессора, закрепить навыки программирования на ассемблере
MASM32 для современных процессоров архитектуры Intel-32.
В ходе выполнения курсовой работы разработаны:
алгоритм и программа для подсчёта функции, заданной индивидуальным заданием.
Разработанная программа выполнена в виде оконного приложения в среде
программирования MASM32. В данной работе представлены схема алгоритма и текст
этой программы.
В данной работе используются WinAPI
(Application Programming Interface) функции. Для работы программы при этом
используются функции арифметического сопроцессора, что позволяет разгрузить
основной процессор и ускорить вычисление операций.
1. Разработка алгоритма
В данном разделе представлены: схемы алгоритмов
программы для подсчёта функции, заданной индивидуальным заданием.
.1 Алгоритм программы для подсчёта функции,
заданной индивидуальным заданием
Программа состоит из двух главных процедур: WinMain
и WndProc, первая из которых
регистрирует класс окна и его основные параметры (размеры окна, цвет фона окна
и т.д.). Во время выполнения первой процедуры вызывается вторая. Процедура WndProc
рассмотрена подробнее в следующем разделе. Алгоритм процедуры WinMain не
представлен, так как в ней последовательно вызываются стандартные команды
создания класса окна.
Схема алгоритма программы для подсчёта функции,
заданной индивидуальным заданием приведена на рисунке 1.
Рисунок 1 - Схема алгоритма программы для
подсчёта функции, заданной индивидуальным заданием
1.2 Алгоритм процедуры программы
В данном разделе приведены схема алгоритма
процедуры WndProc, обрабатывающей сообщения, поступающие от окна. Схема
алгоритма процедуры WndProc представлена на рисунке 2.
Окно в данной курсовой работе состоит из шести TextBox’ов
и двух EditBox’ов.
Через TextBox’ы
выведены инструкции для пользователя. В два EditBox’а
вписываются коэффициенты заданной функции. После ввода коэффициентов они
заносятся в программу и только после нажатия на единственную кнопку они
заносятся в свои переменные и используются для операций в сопроцессоре.
Рисунок 2 - Схема алгоритма процедуры WndProc
Рисунок 2 -Продолжение
2. Разработка программы
В данном разделе представлен текст программы для
подсчёта функции, заданной индивидуальным заданием в соответствии с алгоритмом
из предыдущего раздела. Текст программы из файла "in
out loga(x).asm"
представлен на рисунке 3.
;***************************************************************************
;Волков ;Арифметический сопроцессор; ;Шестнадцатеричная; ; Плавающая точка
(нормальная форма); ; ;
;*************************************************************************** .686 .model flat,stdcall option casemap:none WinMain
proto :DWORD,:DWORD,:DWORD,:DWORD include \masm32\include\windows.inc include
\masm32\include\user32.inc include \masm32\include\kernel32.inc includelib
\masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib include
\masm32\include\masm32.inc includelib \masm32\lib\masm32.lib .data ClassName
db "SimpleWinClass",0 AppName db "5adb",0 MenuName db
"FirstMenu",0 ButtonClassName db "button",0 ButtonText db
"Calculate logA(X)",0 StaticClassName db "static",0
StaticText db "Enter number X", 0 StaticText1 db "Enter number
A", 0 EditClassName db "edit",0 TestString db "Wow! I'm
in an edit box now",0 hwndStatic1 dd 0 hwndStatic2 dd 0 dexpx dd 0
dexpmx dd 0 zero dq 0.0 integer dd 0.0 fractional dd 0.0 fractional_buffer dd
0.0 hex dd 16.0 counter dd 1 divider dd 1 hexInt dd 16 buffer_out db 512 dup(0)
.data? hInstance HINSTANCE ? CommandLine LPSTR ? hwndButton HWND ? hwndEdit
HWND ? hwndEdit1 HWND ? buffer db 512 dup(?) angle dq ? angle1 dq ?
angle_read dq ? angle_buffer dd ?
|
.const ButtonID equ 1 EditID
equ 2 StaticID equ 3 IDM_HELLO equ 1 IDM_CLEAR equ 2 IDM_GETTEXT equ 3
IDM_EXIT equ 4 const_log dq 1.0 .code start: invoke GetModuleHandle, NULL mov
hInstance,eax invoke GetCommandLine mov CommandLine,eax invoke WinMain, hInstance,NULL,CommandLine,
SW_SHOWDEFAULT invoke ExitProcess,eax WinMain proc
hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD LOCAL
wc:WNDCLASSEX LOCAL msg:MSG LOCAL hwnd:HWND mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW mov wc.lpfnWndProc, OFFSET WndProc mov
wc.cbClsExtra,NULL mov wc.cbWndExtra,NULL push hInst pop wc.hInstance mov
wc.hbrBackground,COLOR_BTNFACE+1 mov wc.lpszMenuName,OFFSET MenuName mov
wc.lpszClassName,OFFSET ClassName invoke LoadIcon,NULL,IDI_APPLICATION mov
wc.hIcon,eax mov wc.hIconSm,eax invoke LoadCursor,NULL,IDC_ARROW mov
wc.hCursor,eax invoke RegisterClassEx, addr wc INVOKE
CreateWindowEx,WS_EX_CLIENTEDGE,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\ CW_USEDEFAULT,300,200,NULL,NULL,\
hInst,NULL mov hwnd,eax INVOKE ShowWindow, hwnd,SW_SHOWNORMAL INVOKE
UpdateWindow, hwnd .WHILE TRUE INVOKE GetMessage, ADDR msg,NULL,0,0 .BREAK
.IF (!eax) INVOKE TranslateMessage, ADDR msg INVOKE DispatchMessage, ADDR msg
.ENDW mov eax,msg.wParam ret WinMain endp WndProc proc hWnd:HWND, uMsg:UINT,
wParam:WPARAM, lParam:LPARAM .IF uMsg==WM_DESTROY invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_CREATE ; static1
|
invoke
CreateWindowEx,WS_EX_CLIENTEDGE, ADDR StaticClassName, ADDR StaticText,\
WS_CHILD or WS_VISIBLE or WS_BORDER or ES_LEFT or\ ES_AUTOHSCROLL,\
50,15,200,25,hWnd,StaticID,hInstance,NULL mov hwndStatic1,eax ; edit1 invoke
CreateWindowEx,WS_EX_CLIENTEDGE, ADDR EditClassName,NULL,\ WS_CHILD or
WS_VISIBLE or WS_BORDER or ES_LEFT or\ ES_AUTOHSCROLL,\
50,35,200,25,hWnd,EditID,hInstance,NULL mov hwndEdit,eax invoke SetFocus,
hwndEdit ; static2 invoke CreateWindowEx,WS_EX_CLIENTEDGE, ADDR
StaticClassName, ADDR StaticText1,\ WS_CHILD or WS_VISIBLE or WS_BORDER or
ES_LEFT or\ ES_AUTOHSCROLL,\ 50,70,200,25,hWnd,StaticID,hInstance,NULL mov
hwndStatic1,eax ; edit2 invoke CreateWindowEx,WS_EX_CLIENTEDGE, ADDR
EditClassName,NULL,\ WS_CHILD or WS_VISIBLE or WS_BORDER or ES_LEFT or\
ES_AUTOHSCROLL,\ 50,90,200,25,hWnd,EditID,hInstance,NULL mov hwndEdit1,eax ;
button invoke CreateWindowEx,NULL, ADDR ButtonClassName,ADDR ButtonText,\
WS_CHILD or WS_VISIBLE or BS_DEFPUSHBUTTON,\
75,125,140,25,hWnd,ButtonID,hInstance,NULL mov hwndButton,eax .ELSEIF
uMsg==WM_COMMAND mov eax,wParam .IF lParam==0 .IF ax==IDM_HELLO invoke SetWindowText,hwndEdit,ADDR
TestString invoke SendMessage,hwndEdit,WM_KEYDOWN,VK_END,NULL .ELSEIF
ax==IDM_CLEAR invoke SetWindowText,hwndEdit,NULL .ELSEIF ax==IDM_GETTEXT ;
get number from edit invoke GetWindowText,hwndEdit,ADDR buffer,512 ;invoke
StrToFloat, ADDR buffer, ADDR angle ; преобразуем из ASCII в число с плавающей точкой двойной точности в angle lea esi, buffer call readdec fld angle_read fstp
qword ptr[angle] mov ecx, 20 lea esi, buffer buffer_cliner1: mov byte
ptr[esi],0 inc esi loop buffer_cliner1
|
invoke
GetWindowText,hwndEdit1,ADDR buffer,512 ;invoke StrToFloat, ADDR buffer, ADDR
angle1 ; преобразуем из ASCII в число с плавающей точкой двойной точности в angle lea esi, buffer call readdec fld angle_read fstp qword ptr[angle1] finit ; инициализация сопроцессора fld const_log fld angle FYL2X fld const_log fld angle1
FYL2X FDIVP st(1), st(0) fstp qword ptr[angle] mov ecx, 20 lea esi, buffer
buffer_cliner2: mov byte ptr[esi],0 inc esi loop buffer_cliner2 invoke
FloatToStr, angle, ADDR buffer call DecToHex invoke MessageBox,NULL,ADDR
buffer_out ,ADDR AppName,MB_OK .ELSE invoke DestroyWindow,hWnd .ENDIF .ELSE
.IF ax==ButtonID shr eax,16 .IF ax==BN_CLICKED invoke
SendMessage,hWnd,WM_COMMAND,IDM_GETTEXT,0 .ENDIF .ENDIF .ENDIF .ELSE invoke
DefWindowProc,hWnd,uMsg,wParam,lParam ret .ENDIF xor eax,eax ret WndProc endp readdec proc ;процедура преобразования
символьной строки по адресу ESI в число в сопроцессоре fld zero fstp dword ptr[integer] fld zero fstp dword
ptr[fractional] fld zero fstp dword ptr[fractional_buffer] mov counter, 1
|
xor eax, eax xor edx, edx xor
ecx, ecx mov ebx,16 int_part_read: mov cl,byte ptr[esi] cmp cl, ',' jne
int_part_read_jump1 mov byte ptr[esi],'.' int_part_read_jump1: cmp cl ,'.' ;
jnz int_part_read_jump2 inc esi mov integer,eax ; saved integer part of
number jmp fractional_part_read int_part_read_jump2: .IF (cl>29h
&& cl<40h); sub cl,30h ; .ELSEIF (cl>40h && cl<47h);
sub cl,37h ; .ELSEIF (cl>60h && cl<67h); sub cl,57h ; .ENDIF
mul bl add ax,cx inc esi jmp int_part_read fractional_part_read: xor eax, eax
mov al,byte ptr[esi] .IF( al == 0h) ; string termintor jmp unknow .ELSEIF
(al>29h && al<40h); sub al,30h ; .ELSEIF (al>40h &&
al<47h); sub al,37h ; .ELSEIF (al>60h && al<67h); sub al,57h
.ENDIF mov ecx, counter mov fractional_buffer, eax fild fractional_buffer
modulo_division: fdiv hex loop modulo_division fadd fractional fstp
fractional inc counter inc esi jmp fractional_part_read
|
unknow: fild integer fadd
fractional fstp angle_read ret readdec
endp DecToHex proc
;процедура преобразования символьной строки по адресу ESI в символьню строку
по адресу EDI mov counter,
0 lea esi, buffer xor eax,eax;обнуление eax mov ebx,10 ;
основание системы счисления mov cl, byte ptr [esi] ; проверка ввода
"-" cmp cl,'-' ;
jne DecToHex_m2 jmp exit DecToHex_m2: mov cl, byte ptr [esi] cmp cl,2Eh ; 2E
- it is the point je DecToHex_m1 sub cl, 30h ;перевод из
ASCII mul ebx add eax,ecx inc esi;переход к следующему байту
массива jmp DecToHex_m2
DecToHex_m1: inc esi xor ecx,ecx DecToHex_m3: mov ebx, eax and ebx, 0000000fh
add bl, 30h .if(bl > 39h) add bl, 7 .endif push ebx inc ecx shr eax, 4 cmp
eax, 0 jne DecToHex_m3 lea edi, buffer_out DecToHex_m4: pop ebx mov byte ptr
[edi], bl inc edi loop DecToHex_m4 mov byte ptr[edi], 2Eh ; ставим разделитель inc edi ; ************ с целой частью закончили xor
eax,eax;обнуление eax mov ebx,10 ; основание системы счисления
|
DecToHex_m5: mov cl, byte ptr
[esi] cmp cl, 0 ; 0 - it is end of number je DecToHex_m6 sub cl, 30h ;перевод из
ASCII mul ebx add eax,ecx inc esi;переход к следующему байту
массива jmp DecToHex_m5
DecToHex_m6: cmp eax,0 jnz DecToHex_m7 mov byte ptr[edi], 30h ; ставим ноль и уходим
jmp DecToHex_End DecToHex_m7: .if(eax >= 0 && eax < 10) mov
divider, 10 .elseif(eax >= 10 && eax < 100) mov divider, 100
.elseif(eax >= 100 && eax < 1000) mov divider, 1000 .elseif(eax
>= 1000 && eax < 10000) mov divider, 10000 .elseif(eax >=
10000 && eax < 100000) mov divider, 100000 .elseif(eax >=
100000 && eax < 1000000) mov divider, 1000000 .elseif(eax >=
1000000 && eax < 10000000) mov divider, 10000000 .elseif(eax >=
10000000 && eax < 100000000) mov divider, 100000000 .elseif(eax
>= 100000000 && eax < 1000000000) mov divider, 1000000000
.endif mul hexInt div divider add al, 30h .if(al > 39h) add al, 7 .endif
mov byte ptr[edi], al inc edi cmp edx,0 jz DecToHex_End mov eax,edx inc
counter cmp counter, 2 ja DecToHex_End jmp DecToHex_m7 DecToHex_End: exit:
ret DecToHex endp end start
|
Рисунок 3 - Текст программы "in
out loga(x).asm"
3.
Руководство оператора
В данном разделе представлены: назначение
программы, минимальные системные требования, условия выполнения программы,
описание назначений клавиш.
Данная программа предназначена для подсчёта
функции: при вводе
коэффициентов .
Минимальные системные требования:
) операционная система:
Windows XP;
2) процессор: Pentium
III;
) видео: 800x600;
) оперативная
память:
2
Мб.
Условия выполнения программы:
Коэффициент
a>1.
Ввод в 16-ричной системе счисления.
Работа с программой:
Запускаем еxe-файл. В открывшемся окне (рисунок
4) Для того чтобы рассчитать, нужно ввести коэффициенты .
Коэффициент в первое поле
ввода, коэффициент - во второе поле
ввода. После этого нажимаем кнопку "Calculate
Log a"
и выведется ответ.
Рисунок 4 - Окно программы сразу после запуска
Сообщения оператору:
В данной программе не предусмотрены какие-либо
сообщения оператору, помимо текста в поле диалогового окна.
4. Руководство программиста
В приложении представлены: назначение программы,
условия выполнения программы, описание переменных и функций, используемых в
программе.
Данная программа предназначена для подсчёта
функции: при вводе
коэффициентов . Написана в MASM32
с использованием стандартных библиотек.
Минимальные системные требования:
) операционная система:
Windows XP;
2) процессор: Pentium
III;
) видео: 800x600;
) оперативная
память:
2
Мб.
) Клавиатура, мышь
Условия выполнения программы:
Ввод в 16-ричной системе счисления.
Данная программа использует следующие
переменные:
ClassName
- название класса окна;
AppName
- заголовок окна;
MenuName-
название меню;
ButtonClassName-
название класса кнопки;
ButtonText
- текст на кнопке;
EditClassName
- название класса поля ввода;
TestString - текст
тестовой
строки;-
целое число два;
a - коэффициент а
(формат: строка);
x - коэффициент b
(формат: строка);- ответ после проведения операций в сопроцессоре (формат:
вещественное число);
buffer - ответ
после проведения операций в сопроцессоре (формат: строка);
Используемые библиотеки:
Системные библиотеки kernel32.lib,
user32.lib и gdi32.lib
содержат функции WIN API. Библиотека masm32.lib
содержит функции StrToFloat и FloatToStr.
Рассмотрим основные использованные
функции/процедуры:dwExStyle, // улучшенный стиль окнаlpClassName, // указатель
на зарегистрированное имя классаlpWindowName, // указатель на имя окнаdwStyle,
// стиль окнаx, // горизонтальная позиция окнаy, // вертикальная позиция окнаnWidth,
// ширина окнаnHeight, // высота окнаlpString, // строка символовcbString //
число символовhWnd, // дескриптор окна или элемента управления с
текстомlpString, // адрес буфера для текстаnMaxCount // максимальное число
символов для копированияhWnd, // дескриптор окна или элемента
управленияlpString // адрес строчки
HWND
hWnd, // дескриптор
принимающего окна
UINT
Msg, // отправленное
сообщение
WPARAM
wParam, // дополнительная
конкретизирующая информация
LPARAM
lParam // дополнительная
конкретизирующая информацияфункция перевода строки из ASCII в число с плавающей
точкой двойной точности [3];
stringValue
: string; // преобразуемая
строка
floatValue
: Extended; // полученное
число
FloatToStr-
функция, обратная предыдущей [3];
floatValue
: Extended; // преобразуемое
число
stringValue
: string; // полученная
строка
Использованные команды арифметического
сопроцессора:
finit-
инициализирует арифметический сопроцессор, очистка регистров сопроцессора и его
флагов;
fld- загружает
параметр, написанный после функции, в виде вещественного числа в вершину
стека;загружает целое число, переводит его в вещественное и переносит в вершину
стека;
fadd- сложение
двух вещественных значений. Если без операндов, то складывает ST(0)
и ST(1). Результат в ST(0);производит
деление вещественных чисел. Если без операндов, то делит ST(1)
на ST(0). Результат в ST(0);сохранение
вещественного значения из вершины стека в переменную, указанную после функции,
с выталкиванием.
5.
Вычислительный эксперимент
В данном разделе будут приведены: проверка
возможности ввода различных величин, проверка работоспособности по тестовым
значениям, вывод по вычислительному эксперименту.
Работа с программой осуществляется согласно
указаниям, приведенным в разделе руководство оператора.
Введём в поле ввода числа (рисунок 5) и
убедимся, что программа может их обработать и выдать правильный ответ.
Введённые данные: a=3,
X=0.7.
Ответ:0.2662463(Рисунок 6).
Рисунок 5 - Вычислительный эксперимент 1
Рисунок 6 - Ответ
Проведем следующий вычислительный эксперимент.
Введённые данные: a=0,21, X=0.66.
Ответ:0.2662455(Рисунок 8).
Рисунок 7 - Вычислительный эксперимент 2
Рисунок 8 - Ответ
Вывод: разработанная программа способна
высчитывать функцию, заданную индивидуальным заданием, принимая на вход
положительные числа, высчитывает её правильно.
Заключение
В ходе выполнения курсовой работы были
разработаны алгоритм и программа на языке Assembler
для подсчёта функции, заданной вариантом индивидуального задания. Разработанная
программа соответствует заданным на этапе проектирования требованиям. При
работе над программой были изучены команды арифметического сопроцессора и
изучен алгоритм построения оконного приложения в среде программирования MASM32.
Данная программа состоит из 340 строк. Объем
памяти занимаемый программой составляет: asm-файл
12 Кб, exe-файл 6 Кб, object-файл
6 Кб.
Список литературы
1. Ирвин, Кип. Язык ассемблера для
процессоров Intel, 4-е издание.: Пер. с англ. - М.: Издательский дом
"Вильямс", 2005. - 912 с.
. В.И. Юров Assembler. Учебник для
вузов. 2-ое изд. - СПб.: Питер, 2004. - 637 с.
. Соковиков В. Описание API
функций [Электронный ресурс] // http://vsokovikov.narod.ru/: MSDN - Windows API
по-русски. М., 2010-2014.
URL:http://vsokovikov.narod.ru/New_MSDN_API/Message_queue/fn_sendmessage.htm
(дата обращения: 13.06.2014).