Шаг 13.
Отличия TASM32 от MASM32

    На этом шаге мы рассмотрим изменения в программе для использования TASM32 .

    После разбора программы из предыдущего шага возникает вопрос по поводу ее реализации на ассемблере TASM. В действительности здесь требуются минимальные изменения:


    Пример простой программы для Windows (TASM32).
.386P
;Плоская модель.
.MODEL FLAT, STDCALL
;Константы.
;Сообщение приходит при закрытии окна.
WM_DESTROY	equ 2
;Сообщение приходит при создании окна.
WM_CREATE	equ 1
;Сообщение при щелчке левой кнопкой мыши в области окна.
WM_LBUTTONDOWN equ 201h
;Сообщение при щелчке правой кнопкой мыши в области окна.
WM_RBUTTONDOWN equ 204h
;свойства окна
CS_VREDRAW	equ 1h
CS_HREDRAW	equ 2h
CS_GLOBALCLASS equ 4000h
WS_OVERLAPPEDWINDOW  equ 000CF0000H
style equ CS_HREDRAW+CS_VREDRAW+CS_GLOBALCLASS
;Идентификатор стандартной пиктограммы.
IDI_APPLICATION     equ 32512
 
;Идентификатор курсора.
IDC_CROSS	equ 32515
;Режим показа окна - нормальный.
SW_SHOWNORMAL	equ  1
;Прототипы внешних процедур.
EXTERN    MessageBoxA:NEAR
EXTERN    CreateWindowExA: NEAR
EXTERN    DefWindowProcA:NEAR
EXTERN    DispatchMessageA:NEAR
EXTERN    ExitProcess:NEAR
EXTERN    GetMessageA:NEAR
EXTERN    GetModuleHandleA:NEAR
EXTERN    LoadCursorA:NEAR
EXTERN    LoadIconA:NEAR
EXTERN    PostQuitMessage:NEAR
EXTERN    RegisterClassA:NEAR
EXTERN    ShowWindow:NEAR
EXTERN    TranslateMessage:NEAR
EXTERN    UpdateWindow:NEAR
;Директивы компоновщику для подключения библиотек.
includelib c:\tasm32\lib\import32.lib
 
;Структуры.
;Структура сообщения.
MSGSTRUCT  STRUC	
           MSHWND     DD ? ;Идентификатор окна, получающего сообщение.
           MSMESSAGE  DD ? ;Идентификатор сообщения.
           MSWPARAM   DD ? ;Доп. информация о сообщении.
           MSLPARAM   DD ? ;Доп. информация о сообщении.
           MSTIME     DD ? ;Время посылки сообщения.
           MSPT       DD ? ;Положение курсора во время посылки сообщения.
MSGSTRUCT ENDS	
;-----------------------
WNDCLASS  STRUC	
           CLSSTYLE     DD ? ;Стиль окна.
           CLWNDPROC    DD ? ;Указатель на процедуру окна.
           CLSCEXTRA    DD ? ;Информация о доп. байтах для данной структуры.
           CLWNDEXTRA   DD ? ;Информация о доп. байтах для окна.
           CLSHINSTANCE DD ? ;Дескриптор приложения.
           CLSHICON     DD ? ;Идентификатор иконки окна.
           CLSHCURSOR   DD ? ;Идентификатор курсора окна.
           CLBKGROUND   DD ? ;Идентификатор кисти окна.
           CLMENUNAME   DD ? ;Имя-идентификатор меню.
           CLNAME       DD ? ;Специфицирует имя класса окон.
WNDCLASS  ENDS 
;Сегмент данных. 
_DATA SEGMENT DWORD PUBLIC USE32 'DATA'
     NEWHWND    DD 0
     MSG        MSGSTRUCT <?>
     WC         WNDCLASS <?>
     HINST       DD 0 ;Здесь хранится дескриптор приложения.
     TITLENAME   DB 'Простой пример 32-битного приложения',0
     CLASSNAME   DB 'CLASS32',0
     CAP         DB 'Сообщение',0
     MES1        DB 'Вы нажали левую кнопку мыши',0
     MES2        DB 'Выход из программы. Пока!',0
_DATA ENDS 
;Сегмент кода.
_TEXT SEGMENT DWORD PUBLIC USE32 'CODE' 
START: 
;Получить дескриптор приложения.
     PUSH  0
     CALL  GetModuleHandleA
     MOV   [HINST], EAX
REG_CLASS:
;Заполнить структуру окна.
;Стиль.
     MOV [WC.CLSSTYLE], style 
;Процедура обработки сообщений.
     MOV   [WC.CLWNDPROC], OFFSET WNDPROC
     MOV   [WC.CLSCEXTRA], 0
     MOV   [WC.CLWNDEXTRA], 0
     MOV   EAX, [HINST]
     MOV   [WC.CLSHINSTANCE], EAX
 
;------------ пиктограмма окна
    PUSH    IDI_APPLICATION
    PUSH    0
    CALL    LoadIconA
    MOV    [WC.CLSHICON], EAX
;------------ курсор окна
    PUSH   IDC_CROSS
    PUSH   0
    CALL   LoadCursorA
    MOV    [WC.CLSHCURSOR], EAX
;------------
    MOV    [WC.CLBKGROUND], 17   ;Цвет окна.
    MOV    DWORD PTR [WC.CLMENUNAME],0
    MOV    DWORD PTR [WC.CLNAME], OFFSET  CLASSNAME
    PUSH   OFFSET WC
    CALL   RegisterClassA
;Создать окно зарегистрированного класса.
    PUSH   0
    PUSH   [HINST]
    PUSH   0
    PUSH   0
    PUSH   400 ;   DY - высота окна.
    PUSH   400 ;   DX - ширина окна.
    PUSH   100 ;  Y - координата левого верхнего угла.
    PUSH   100 ;  X - координата левого верхнего угла.
    PUSH   WS_OVERLAPPEDWINDOW
    PUSH      OFFSET TITLENAME  ;Имя окна.
    PUSH      OFFSET CLASSNAME  ;Имя класса.
    PUSH   0
    CALL    CreateWindowExA
;Проверка на ошибку.
    CMP        EAX,0
    JZ    _ERR
    MOV   [NEWHWND], EAX  ;Дескриптор окна.
;------------------------------------
    PUSH  SW_SHOWNORMAL
    PUSH  [NEWHWND]
    CALL  ShowWindow    ;Показать созданное окно.
;------------------------------------
    PUSH  [NEWHWND]
    CALL UpdateWindow     ;Команда перерисовать видимую
                          ;часть окна, сообщение WM_PAINT.
;Цикл обработки сообщений 
MSG_LOOP:
    PUSH 0
    PUSH 0
    PUSH 0
    PUSH OFFSET MSG
    CALL GetMessageA
    CMP  EAX, 0
    JE   END_LOOP
    PUSH  OFFSET MSG
    CALL TranslateMessage
    PUSH OFFSET MSG
    CALL DispatchMessageA
    JMP  MSG_LOOP 
END_LOOP: 
;Выход из программы (закрыть процесс).
    PUSH  [MSG.MSWPARAM]
    CALL ExitProcess 
_ERR:
    JMP  END_LOOP
;-----------------------------------------
;Процедура окна.
;Расположение параметров в стеке: 
;[ЕВР+014Н] LPARAM 
;[ЕВР+10Н] WAPARAM 
;[ЕВР+0СН] MES 
;[ЕВР+8] HWND 
WNDPROC PROC
        PUSH EBP
        MOV  EBP, ESP
        PUSH  EBX
        PUSH ESI
        PUSH EDI
        CMP  DWORD PTR [EBP+0CH], WM_DESTROY
        JE   WMDESTROY
        CMP  DWORD PTR [EBP+0CH], WM_CREATE
        JE   WMCREATE
        CMP  DWORD PTR   [EBP+0CH],WM_LBUTTONDOWN   ;Левая кнопка.
        JE   LBUTTON
        CMP  DWORD PTR   [EBP+0CH],WM_RBUTTONDOWN   ;Правая кнопка.
        JE   RBUTTON
        JMP  DEFWNDPROC
;Нажатие правой кнопки приводит к закрытию окна.
RBUTTON:
        JMP  WMDESTROY 
;Нажатие левой кнопки мыши. 
LBUTTON: 
;Выводим сообщение.
        PUSH 0 ;МВ_ОК
        PUSH OFFSET CAP
        PUSH OFFSET MES1
        PUSH DWORD PTR [EBP+08H]
        CALL MessageBoxA
        MOV  EAX,0
        JMP  FINISH
WMCREATE:	
        MOV  EAX,0
        JMP  FINISH
DEFWNDPROC:	
        PUSH DWORD PTR [EBP+14H]
        PUSH DWORD PTR [EBP+10H]
        PUSH DWORD PTR [EBP+0CH]
        PUSH DWORD PTR [EBP+08H]
        CALL DefWindowProcA
        JMP  FINISH
WMDESTROY:	
        PUSH 0  ;MB_OK
        PUSH OFFSET CAP
        PUSH OFFSET MES2
        PUSH DWORD PTR [EBP+08H]   ;Дескриптор окна.
        CALL MessageBoxA
        PUSH 0
        CALL PostQuitMessage   ;Сообщение WM_QUIT.
        MOV  EAX, 0
FINISH:	
        POP  EDI
        POP  ESI
        POP  EBX
        POP  EBP
        RET  16
WNDPROC ENDP
_TEXT   ENDS	
        END START	
Текст этой программы можно взять здесь.

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

    Обратите внимание на то, как задаются свойства окон. Описание этих свойств можно найти в программе помощи для функции CreateWindow.

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

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

    Часть API-функций получила суффикс "А". Дело в том, что функции имеют два прототипа:

    На следующем шаге мы рассмотрим передачу параметров через стек.




Предыдущий шаг Содержание Следующий шаг