При розробці програмних додатків на мові асемблер дуже важливим є обробка дійсних чисел. В даній статті буде наочно обяснено основні ньюанси використання дійсних в програмах. Але спочатку про код програми. Програма починається з:
.386 .model flat,stdcall option casemap:none include \masm32\include\windows.inc include \masm32\include\user32.inc include \masm32\include\kernel32.inc include \masm32\include\gdi32.inc include \masm32\include\comdlg32.inc include \masm32\include\shell32.inc include \masm32\include\masm32.inc include \masm32\include\fpu.inc includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib includelib \masm32\lib\gdi32.lib includelib \masm32\lib\comdlg32.lib includelib \masm32\lib\shell32.lib includelib \masm32\lib\masm32.lib includelib \masm32\lib\fpu.lib
Цей код визначає інструкції, які може використовувати компялітор під час створення низькорівневого коду програми. Далі необхідно оголости необхідні дані: .const Button_1ID equ 1 ; унікальний номер вікна Edit_1ID equ 2 ... .data? hwndButton1 HWND ? hwndEdit1 HWND ? buffer db 512 dup(?) ; буфер необхідний при копіюванні з Едіта або в Едіт
... .data TextButton1 db "Кнопка",0 TextEdit1 d "3.14",0 rX dq 0.0 ; змінна в якій буде зберігатисьрезультат ...
Завдання. На фрмі розмістити Едіт та кнопку, після натиснення на яку програма змінює значеня в Едіті на теж значення пмножене на число ПІ. В обробнику події BN_CLICKED нашої кнопки запишемо наступний код: ... .IF ax==Button_1ID shr eax, 16 .IF ax==BN_CLICKED invoke Calculate ; виклик процедури яка виконає дії згідно із нашим завданням .ENDIF .ENDIF ...
Calculate proc ;** Зберігаємо в змінній "rX" число із Едіта invoke GetWindowTextLength, hwndEdit1 ; визначаємо довжину текста в Едіті mov ecx,eax ; значення повернеться в EAX add ecx,1 invoke GetWindowText, hwndEdit1, addr buffer, ecx ; Копіювання тексту в буферну змінну invoke StrToFloat, addr buffer,ADDR rX ; Виклик процедури конвертції (перший парам. - адрес вхідного буферу, 2-ий - адрес змінної розмірністю QWORD тобто 8 байт)
finit ; ініціаліація співпроцесора fldpi ; загрузка числаПІ в стек fmul rX ; множення вершини стеку на наше чсло fstp rX ; Збереження в память нового значення invoke FloatToStr, rX, addr buffer ; зворотня функця StrToFloat (параметри аналогічі) invoke SetWindowText, hwndEdit1, addr buffer ; Зміна тексту в Едыты ret Calculate endp Ми можем також ускладнити наше завдання. Наприклад, якщо число в Едіт відємне то поміняти його знак на додатній. Для цього необхідно змінити процедуру CALCULATE :Calculate proc ;** Зберігаємо в змінній "rX" число із Едіта invoke GetWindowTextLength, hwndEdit1 ; визначаємо довжину текста в Едіті mov ecx,eax ; значення повернеться в EAX add ecx,1 invoke GetWindowText, hwndEdit1, addr buffer, ecx ; Копіювання тексту в буферну змінну invoke StrToFloat, addr buffer,ADDR rX ; Виклик процедури конвертції (перший парам. - адрес вхідного буферу, 2-ий - адрес змінної розмірністю QWORD тобто 8 байт)
finit ; ініціаліація співпроцесора
sahf fldz ; Загрузка нуля fld rX ; Наше значення fcom ; виклик процедури порівняння fstsw ax ; бла-бла-бла sahf jae mMultipl1 ; якщо знчення більше рівне нулю то переходимо на мітку множення fchs ; інакше змінюємо знак (CHangeSign)
mMultipl1: fldpi ; загрузка числаПІ в стек fmul rX ; множення вершини стеку на наше чсло fstp rX ; Збереження в память нового значення invoke FloatToStr, rX, addr buffer ; зворотня функця StrToFloat (параметри аналогічі) invoke SetWindowText, hwndEdit1, addr buffer ; Зміна тексту в Едыты ret Calculate endp
PS Дякую за увагу. Руслан.
|