Четверг, 24.07.2025, 18:37 Приветствую Вас Гость

On-line: Книги, учебники, статьи

Главная | Регистрация | Вход | RSS

Глава 7. Использование ассемблера с языками высокого уровня(5)

Трансляция.

1-й способ.

 tasm32 /ml dialforc.asm
 brcc32 dialforc.rc
Далее включаем в проект для программы на Рис. 3.7.5 файлы dialforc.obj и dialforc.res.

2-й способ.
Отличается от предыдущего тем, что в проект включается файл dialforc.rc, а не dialforc.res. Разумеется, определения констант оттуда следует убрать, т.к. они имеются в подключаемых Си head-файлах.

IV

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

// calcc.срр
#include <windows.h>
#include <stdio.h>

// вызов главной ассемолернои процедуры
extern "С" _stdcall MAIN1();
// сложить
extern "С" _stdcall void sum(char *, char *, char *);
// вычесть
extern "C" _stdcall void su(char *, char *, char *);
// умножить
extern "C" _stdcall void mu(char *, char *, char *);
// разделить
extern "C" _stdcall void dii(char *, char *, char *);

int WINAPI WinMain (HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR lpszArgs, int nWinMode)
{
 MAIN1();
 return 0;
}

extern "C" _stdcall void sum(char * s1, char * s2, char * s)
{
 float f1,f2,f;
 f1=atof(s1);
 f2=atof(s2);
 f=f1+f2;
 sprintf(s,"%f",f);
 strcat(s," +");
 return;
}

extern "C" _stdcall void su(char * s1, char * s2, char * s)
{
 float f1,f2,f;
 f1=atof(s1); f2=atof(s2);
 f=f1-f2;
 sprintf(s,"%f",f);
 strcat(s," -");
 return;
}

extern "C" _stdcall void mu(char * s1, char * s2, char * s)
{
 float f1,f2,f;
 f1=atof(s1); f2=atof(s2);
 f=f1*f2;
 sprintf(s,"%f",f);
 strcat(s," *");
 return;
}

extern "C" __stdcall void dii(char * s1, char * s2, char * s)
{
 float f1,f2,f;
 f1=atof(s1); f2=atof(s2);
 if(f2!=0)
 {
 f=f1/f2;
 sprintf(s,"%f",f);
 strcat(s," /");
 } else strcpy(s,"Ошибка деления");
 return;
}

Рис. 3.7.7. Си-модуль для программы простейшего калькулятора, компонуемый с ассемблерным модулем на Рис. 3.8.8.

// calc.rc
// определение констант
// стили окна
#define WS_SYSMENU 0x00080000L
#define WS_MINIMIZEBOX 0x00020000L
#define DS_3DLOOK 0x0004L
#define ES_LEFT 0x0000L
#define WS_CHILD 0x40000000L
#define WS_VISIBLE 0x10000000L
#define WS_BORDER 0x00800000L
#define WS_TABSTOP 0x00010000L
#define SS_LEFT 0x00000000L
#define BS_PUSHBUTTON 0x00000000L
#define BS_CENTER 0x00000300L
#define DS_LOCALEDIT 0x20L
#define ES_READONLY 0x0800L

// идентификаторы кнопок
#define IDC_BUTTON1 101
#define IDC_BUTTON2 102
#define IDC_BUTTON3 103
#define IDC_BUTTON4 104
DIAL1 DIALOG 0, 0, 170, 110
STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | DS_3DLOOK
CAPTION "Пример простейшего калькулятора"
FONT 8, "Arial"
{
 CONTROL "", 1, "edit", ES_LEFT | WS_CHILD | WS_VISIBLE
 | WS_BORDER | WS_TABSTOP, 9, 8, 128, 12
 CONTROL "", 2, "edit", ES_LEFT | WS_CHILD | WS_VISIBLE
 | WS_BORDER | WS_TABSTOP, 9, 27, 128, 12
 CONTROL "", 3, "edit", ES_LEFT | WS_CHILD | ES_READONLY
 | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 9, 76, 127, 12
 CONTROL "+", IDC_BUTTON1, "button", BS_PUSHBUTTON
 | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 11, 48, 15, 14
 CONTROL "-", IDC_BUTTON2, "button", BS_PUSHBUTTON
 | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 34, 48, 15, 14
 CONTROL "*", IDC_BUTTON3, "button", BS_PUSHBUTTON
 | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 56, 48, 15, 14
 CONTROL "/", IDC_BUTTON4, "button", BS_PUSHBUTTON
 | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 80, 48, 15, 14
}


; calc. inc
; константы
; сообшение приходит при закрытии окна
WM_CLOSE equ 10h
WM_INITDIALOG equ 110h
WM_COMMAND equ 111h
WM_GETTEXT equ 0Dh
WM_SETTEXT equ 0Ch

; прототипы внешних процедур
EXTERN ExitProcess:NEAR
EXTERN GetModuleHandleA:NEAR
EXTERN DialogBoxParamA:NEAR
EXTERN EndDialog:NEAR
EXTERN SendDlgItemMessageA:NEAR

; структуры
; структура сообщения
MSGSTRUCT STRUC
 MSHWND DWORD ?
 MSMESSAGE DWORD ?
 MSWPARAM DWORD ?
 MSLPARAM DWORD ?
 MSTIME DWORD ?
 MSPT DWORD ?
MSGSTRUCT ENDS

; модуль calc.asm
.386P
; поская модель
.MODEL FLAT, stdcall
include calc.inc
EXTERN sum:NEAR
EXTERN su:NEAR
EXTERN mu:NEAR
EXTERN dii:NEAR
PUBLIC MAIN1

; директивы компоновщику для подключения библиотек
includelib c:\tasm32\lib\import32.lib
;------------------------------------------------

;сегмент данных
_DATA SEGMENT DWORD PUBLIC USE32 'DATA'
 MSG MSGSTRUCT <?>
 HINST DD 0 ; дескриптор приложения
 PA DB "DIAL1",0
 S1 DB 50 DUP (0)
 S2 DB 50 DUP (0)
 S DB 50 DUP (0)
_DATA ENDS

; сегмент кода
_TEXT SEGMENT DWORD PUBLIC USE32 'CODE'
; процедура, вызываемая из Си-модуля
MAIN1 PROC
; получить дескриптор приложения
 PUSH 0
 CALL GetModuleHandleA
 MOV [HINST], EAX
;-------------------------------------------
 PUSH 0
 PUSH OFFSET WNDPROC
 PUSH 0
 PUSH OFFSET PA
 PUSH [HINST]
 CALL DialogBoxParamA
;-------------------------------------------
 RET
MAIN1 ENDP

; процедура окна
; расположение параметров в стеке
; [EBP+014Н] ; LPARAM
; [EBP+10Н] ; WAPARAM
; [EBP+0CH] ; MES
; [EBP+8] ; HWND
WNDPROC PROC
 PUSH EBP
 MOV EBP,ESP
;-------------------------------------------
 CMP DWORD PTR [EBP+0CH],WM_CLOSE
 JNE L1
 PUSH 0
 PUSH DWORD PTR [EBP+08H]
 CALL EndDialog
 MOV EAX,1
 JMP FINISH
L1:
 CMP DWORD PTR [EBP+0CH],WM_INITDIALOG
 JNE L2
; здесь заполнить окна редактирования, если надо

 JMP FINISH
L2:
 CMP DWORD PTR [EBP+0CH],WM_COMMAND
 JNE FINISH
 CMP WORD PTR [EBP+10H],101
 JNE NO_SUM
; первое слагаемое
 PUSH OFFSET S1
 PUSH 50
 PUSH WM_GETTEXT
 PUSH 1
 PUSH DWORD PTR [EBP+08H]
 CALL SendDlgItemMessageA
; второе слагаемое
 PUSH OFFSET S2
 PUSH 50
 PUSH WM_GETTEXT
 PUSH 2
 PUSH DWORD PTR [EBP+08H]
 CALL SendDlgItemMessageA
; сумма
 PUSH OFFSET S
 PUSH OFFSET S2
 PUSH OFFSET S1
 CALL sum
; вывести сумму
 PUSH OFFSET S
 PUSH 50
 PUSH WM_SETTEXT
 PUSH 3
 PUSH DWORD PTR [EBP+08H]
 CALL SendDlgItemMessageA
 JMP FINISH
NO_SUM:
 CMP WORD PTR [EBP+10H],102
 JNE NO_SUB
; уменьшаемое
 PUSH OFFSET SI
 PUSH 50
 PUSH WM_GETTEXT
 PUSH 1
 PUSH DWORD PTR [EBP+08H]
 CALL SendDlgItemMessageA
; вычитаемое
 PUSH OFFSET S2
 PUSH 50
 PUSH WM_GETTEXT
 PUSH 2
 PUSH DWORD PTR [EBP+08H]
 CALL SendDlgItemMessageA
; разность
 PUSH OFFSET S
 PUSH OFFSET S2
 PUSH OFFSET S1
 CALL su
; вычислить разность
 PUSH OFFSET S
 PUSH 50
 PUSH WM_SETTEXT
 PUSH 3
 PUSH DWORD PTR [EBP+08H]
 CALL SendDlgItemMessageA
 JMP FINISH
;
NO_SUB:
 CMP WORD PTR [EBP+10H],103
 JNE NO_MULT
; первый множитель
 PUSH OFFSET S1
 PUSH 50
 PUSH WM_GETTEXT
 PUSH 1
 PUSH DWORD PTR [EBP+08H]
 CALL SendDlgItemMessageA
; второй множитель
 PUSH OFFSET S2
 PUSH 50
 PUSH WM_GETTEXT
 PUSH 2
 PUSH DWORD PTR [EBP+08H]
 CALL SendDlgItemMessageA
; произведение
 PUSH OFFSET S
 PUSH OFFSET S2
 PUSH OFFSET S1
 CALL mu
; вывести произведение
 PUSH OFFSET S
 PUSH 50
 PUSH WM_SETTEXT
 PUSH 3
 PUSH DWORD PTR [EBP+08H]
 CALL SendDlgItemMessageA
 JMP FINISH
;
NO_MULT:
 CMP WORD PTR [EBP+10H],104
 JNE FINISH
; делимое
 PUSH OFFSET S1
 PUSH 50
 PUSH WM_GETTEXT
 PUSH 1
 PUSH DWORD PTR [EBP+08H]
 CALL SendDlgItemMessageA
; делитель
 PUSH OFFSET S2
 PUSH 50
 PUSH WM_GETTEXT
 PUSH 2
 PUSH DWORD PTR [EBP+08H]
 CALL SendDlgItemMessageA
; деление
 PUSH OFFSET S
 PUSH OFFSET S2
 PUSH OFFSET S1
 CALL dii
; вывести результат деления
 PUSH OFFSET S
 PUSH 50
 PUSH WM_SETTEXT
 PUSH 3
 PUSH DWORD PTR [EBP+08H]
 CALL SendDlgItemMessageA
 JNE FINISH

FINISH:
 MOV EAX,0
 POP EBP
 RET 16
WNDPROC ENDP
_TEXT ENDS
END

Вход на сайт
Поиск
Календарь
«  Июль 2025  »
ПнВтСрЧтПтСбВс
 123456
78910111213
14151617181920
21222324252627
28293031
Архив записей
Наш опрос
Как Вам удобнее??
Всего ответов: 341
Мини-чат
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Статистика

    Онлайн всего: 2
    Гостей: 2
    Пользователей: 0