Пример программы на masm

1) EX1: ПРОСТЕЙШАЯ ПРОГРАММА, СООБЩАЮЩАЯ О ТОМ, ЧТО ЕЕ ЗАПУСТИЛИ.

2) EX2+EX2A: КОМБИНАЦИИ СЕГМЕНТОВ (common-public).

3) EX3: СЛОВА И БАЙТЫВ ПАМЯТИ.

4) EX4: СЛОВА И БАЙТЫВ РЕГИСТРАХ

5) EX5: ЦЕЛЫЕ ДВОИЧНЫЕ (С ФИКС.ТОЧКОЙ) В ПАМЯТИ И РЕГИСТРАХ

6) EX6: АРИФМЕТИКА ДВОИЧНЫХ ЦЕЛЫХ:Y=(A+4-B)*2/C.

7) EX7: ВЕТВЛЕНИЯ, ПЕРЕХОДЫ, ЦИКЛЫ.

8) EX8: ИНДЕКСАЦИЯ.

9) EX9: ИМЕНА И ВЫРАЖЕНИЯ.

10) EX10: СТРОКИ СИМВОЛОВ В ПАМЯТИ И РЕГИСТРАХ

11) EX11: ПЕРЕСЫЛКА СТРОКИ СИМВОЛОВ

12) EX12: ПОИСК ПРОБЕЛА В СТРОКЕ СИМВОЛОВ

13) EX13: СРАВНЕНИЕ СТРОК

14) EX14: БЛИЖНЯЯ ПРОЦЕДУРА С ДВУМЯ ПАРАМЕТРАМИ (ПО ЗНАЧЕНИЮ)

15) EX15: БЛИЖНИЙ ВЫЗОВ БЕЗ ПРОЦЕДУРЫ(АНАЛОГ EX13 С ПОМЕЧЕННОЙ П/П)

16) EX16: БЛИЖНЯЯ ПРОЦЕДУРА С ТРЕМЯ ПАРАМЕТРАМИ (ПО БЛИЖНЕМУ АДРЕСУ)

17) EX17: БЛИЖНЯЯ ПРОЦЕДУРА С ТРЕМЯ ПАРАМЕТРАМИ (ПО ДАЛЬНЕМУ АДРЕСУ)

18) EX18+EX18A: МЕЖМОДУЛЬНЫЕ ССЫЛКИ (ДАННЫЕ И МЕТКИ).

19) EX19+EX19A: ВЫЗОВ ВНЕШНЕЙ БЛИЖНЕЙ ПРОЦЕДУРЫ.

#1 Первая программа на ассемблере MASM

20) EX20+EX20A: ВЫЗОВ ВНЕШНЕЙ ДАЛЕКОЙ ПРОЦЕДУРЫ(ПАР.ПО ДАЛЬН.АДРЕСУ)

21) EX21: ДАЛЕКАЯ ПРОЦЕУРА — ОБРАЩЕНИЕ К DOS (INT 21H)

22) EX22: ПОЛЬЗОВАТЕЛЬСКИЙ ОБРАБОТЧИК ПРЕРЫВАНИЯ.

23) EX23: ПОВТОРЯЕМЫЕ БЛОКИ REPT, IRP, IRPC.

24) DX01: ДИСКИ-ФАЙЛЫСРЕДСТВАМИ DOS:

FAT-сколько места;DTA-поиск файлов.

25) DX02: ДИСКИ-ФАЙЛЫСРЕДСТВАМИ DOS:

поиск файла и извлечение полей оглавления из DTA

DX03: HANDLE-ФАЙЛЫ:СОЗДАНИЕ,ОТКРЫТИЕ,ПОЗИЦИОНИР.,ИЗМЕРЕНИЕ,В/В

; EX1: ПРОСТЕЙШАЯ ПРОГРАММА, СООБЩАЮЩАЯ О ТОМ, ЧТО ЕЕ ЗАПУСТИЛИ.

data segment;-именование сегмента.

str db «Пример программы»,13,10,»$»;-объявление данных.

data ends;-конец сегмента.

code segment;-именование сегмента.

assume cs:code,ds:data;-сементные регистры.

start:;-метка точки входа.

mov ax,data;-адрес сегмента данных.

mov ds,ax; в регистр ds.

mov dx,offset str;-адрес вых.строки в dx.

mov ah,09h;-обращение к системной.

int 21h; функции вывода строки.

u_show_r16 ds,’Сегмент данных: ‘

u_show_r16 cs,’Сегмент кода: ‘

mov ah,4ch;-обращение к сис.функ.

int 21h; завершения программы.

code ends;-конец сегмента.

stack segment stack;-именование сегмента.

dw 64 dup(?);-место для стека.

stack ends;-конец сегмента.

end start;-конец исходного модуля

; и имя точки входа

; EX2: КОМБИНАЦИИ СЕГМЕНТОВ. Первая половина.

; Этот пример «собирается» из двух исходников EX2.ASM и EX2A.ASM,

; которые по отдельности транслируются и совместно линкуются:

; Сегменты данных накладываются (EX2A на EX2),а сегмент кода до-

; полнится сегментом кода из EX2A.

data segment byte common; COMMON-на этот сегмент наложится

str db «Пример»; такой же сегмент из EX2A.

data ends; BYTE-выравнивание по байтам.

code segment byte public; PUBLIC-этот сегмент дополнится

assume cs:code,ds:data; таким же сегментом из EX2A,на-

Hello World на Ассемблере (x86)

; чиная со следующего байта.

mov dx,offset str; Программа не закончена, она

; продолжится командами из кодо-

; вого сегмента EX2A.

stack segment stack

; EX2A: КОМБИНАЦИИ СЕГМЕНТОВ. Вторая половина.

; Этот пример «собирается» из двух исходников EX2.ASM и EX2A.ASM,

; которые по отдельности транслируются и совместно линкуются:

; Сегменты данных накладываются (EX2A на EX2),а сегмент кода до-

; полнится сегментом кода из EX2A.

data segment byte common

db » Наложение данных (common)»,13,10

db » Сложение кодов (public)»,13,10,»$»

; COMMON-этот сегмент наложится

; на такой же сегмент из EX2.

; BYTE-выравнивание по байтам.

code segment byte public; PUBLIC-этот сегмент дополняет

mov ah,09h; такой же сегмент из EX2.

int 21h; Команды логически продолжают

mov ah,4ch; программу из EX2.

; EX3: СЛОВА И БАЙТЫВ ПАМЯТИ.

; В программе шестнадцатеричные величины записываются слева на-

; право. В памяти каждыий байт читается слева направо, но:

; — байты в слове читаются справа налево,

; — слова в двойном слове читаются справа налево.

xbyte db 12h,34h,0ABh;-поле из трех байт: 12 34 AB

xword dw 5678h,1A1Bh;-поле из двух слов: 7856 1B1A

xdword dd 2A2B2C2Dh;-двойное слово: 2D2C2B2A

Источник: poisk-ru.ru

Пример программы на masm

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

Базовое приложение на FASM под Win32:

format PE GUI 4.0 entry MyEntry ;;## Файл Win32ax.inc отличается от Win32a тем что ;;## содержит кроме всего проче, макросы для высокоувроневых ;;## конструкций по типу if-else ,while итд. include ‘C:INCLUDEWin32ax.inc’ ;;## Минимальный exe-файл может состоять из 2 секций — секции кода ;;## расположенной ниже и секции импорта расположенной сразу после ;;## секции кода. section ‘.code’ code readable executable MyEntry: ;;## Если код заканчивается не этой функцией то ;;## закрытие приложение считается некорректным ;;## и программа вылетает с ошибкой, вместо мирного выхода. ;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Тут мог быть ваш код:) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;; invoke ExitProcess,0 section ‘.idata’ import data readable writeable ;;## Импорт функций состоит из двух частей. ;;## Импорт DLL-файлов и собественно сам импорт ;;## функций из них. FASM не нуждается в LIB файлах ;;## с функциями — он прекрасно вытаскивает их и из ;;## обычных DLL. По этой же причине в комплекте ;;## нет линкера — он встроен в сам транслятор. library kernel32, ‘KERNEL32.DLL’, user32, ‘USER32.DLL’, ntdll, ‘NTDLL.DLL’ ;;## Слеш сигнализирует компилятору что это все еще одна строка. ;;## В данном случае все таблицы импорта берутся из include файлов ;;## но не для всех системных DLL есть include-файлы со списками импорта. ;;## Имя импорт-ресурса(псевдоним DLL выше). И имя функции + псевдоним в ваше коде. ;;## Можно хоть кулаком по клавиатуре назвать функцию в коде — главное правильно ;;## написать имя импортируемой функции в DLL. import ntdll, stringprint,’sprintf’, itoa,’_itoa’, atoi,’atoi’ ;;## Примечание — импортируются только те функции которые хоть раз использованы в коде ;;## не страшитесь длинных списков импорта — больше от этого ваши программы не станут. ;;## хотя хорошей шпаргалкой служит именно ручной импорт только нужных функции. ;;## Так вы можете сразу посмотреть что импортировали и чем придется оперировать. include ‘C:INCLUDEAPIAKernel32.inc’ include ‘C:INCLUDEAPIAUser32.inc’

Базовое оконное приложение на FASM:
format PE GUI 4.0 entry MyEntry include ‘C:INCLUDEWin32ax.inc’ section ‘.data’ data readable writeable ;;## В секции данных представлены 2 строки и 2 класса нужных для создания окна. ;;## szClsName обязательная строка — это имя класса окна, который мы зарегиструем. ;;## поиск среди классов окон ведется именно по этому ключевому параметру. szClsName db «TestWndClass»,0 szWindowName db «Tutorial #1»,0 ;;## WNDCLASS это структура класса окна, в ней содержится самая разная информация. ;;## от иконки и курсора, до адреса процедуры обработки сообщений. wCls WNDCLASS ;;## Структура MSG это структура которая принимает сообщения и из нее же ;;## берут нужные данные пре-обработчики этих сообщений. wMsg MSG section ‘.code’ code readable executable MyEntry: ;;## Заполняем структуру WNDCLASS нужными данными. ;;## CS_VREDRAW и CS_HREDRAW это стили которые отвечают за ;;## перерисовку окна при измении высоты и ширины сответственно. mov [wCls.style],CS_VREDRAW+CS_HREDRAW ;;## Указываем процедуру обработки окна. В данном случае в поле lpfnWndProc ;;## помещается адрес нашей процедуры обработки сообщений — WndProc. mov [wCls.lpfnWndProc],WndProc ;;## Помещаем в структуру адрес на строку с именем нашего класса mov [wCls.lpszClassName],szClsName ;;## Указываем цвет фона окна.

Читайте также:
Программа на увеличение количества отжиманий

В данном случае это белый. mov [wCls.hbrBackground],COLOR_WINDOW+1 ;;## После занесения всех нужных данных можно регистрировать класс. invoke RegisterClass,wCls ;;## Создаем само окно. Второй параметр это как раз адрес на строку ;;## именем класса нашего окна.

По этому параметру будет найден наш класс. ;;## invoke CreateWindowEx,0,szClsName,szWindowName, ;;## WS_VISIBLE стиль — указывает на то что окно будет сразу видно. ;;## Если его не указать, окно можно будет показать функцией ShowWindow ;;## вызвав ее единожды. Скрыть окно тоже можно — той же функцией но с другим ;;## параметров — SW_HIDE а не SW_SHOW. ;;## WS_SYSMENU указывает на то что бы к окну были добавлены кнопки, свернуть ;;## максимизировать и закрыть. WS_VISIBLE or WS_SYSMENU, ;;## Кордината Х кордината Y ;;## длина и ширина. А так же некоторые другие пока не нужные нам параметры. ;;## о которых будет рассказано в следующем примере. 200,200,200,200,0,0,0,0
«Тяжело в учении, легко в бою» — А.В. Суворов
somewhere else
Участник клуба
Регистрация: 17.07.2008
Сообщений: 1,409
Продолжение второго примера:
;;## После создания окна можно запускать цикл приема сообщений. ;;## Пока поступают сообщений, программа «живет» Если сообщений нет ;;## программа закрывается. .message_loop: ;;## Получаем следующее сообщение. Если есть переходим к обработки, если нет — выходим invoke GetMessage,wMsg,0,0,0 cmp eax,0 je .exit ;;## Пред-Обработка сообщений и передача их функции обрабтчику. invoke TranslateMessage,wMsg invoke DispatchMessage,wMsg jmp .message_loop .exit: invoke ExitProcess,0 proc WndProc hWnd,uMsg,wParam,lParam ;;## Изменять эти регистры, регистры «нежелательно» потому перед ;;## обработкой они сохраняются, а после восстанавливаются. push edi esi ebx ;;## для удобства поместим сообщение в EAX mov eax,[uMsg] ;;## Ряд сравнений сообщения с обрабатываемыми. cmp eax,WM_CLOSE je wmClose cmp eax,WM_CREATE je wmCreate ;;## если совпадений не найдено, передаем сообщений стандартной процедуре обработки ;;## окна. Это кстати она рисует само окно, перерисовывает его когда нужно итд. invoke DefWindowProc,[hWnd],[uMsg],[wParam],[lParam] jmp pEnd wmCreate: ;;## Обработчик сообщений WM_CREATE jmp pEnd wmClose: ;;## Обработчик сообщения WM_CLOSE ;;## Функция PostQuitMessage закрывает окно, вернее посылает стандартной процедуре ;;## сообщение закрытия. invoke PostQuitMessage,0 pEnd: ;;## Как и говорилось выше регистры восстанавливаются после обработки. pop ebx esi edi ret endp section ‘.idata’ import data readable writeable library kernel32, ‘KERNEL32.DLL’, user32, ‘USER32.DLL’ include ‘C:INCLUDEAPIAKernel32.inc’ include ‘C:INCLUDEAPIAUser32.inc’
Тоже самое но уже с макросами — для наглядности:
format PE GUI 4.0 entry MyEntry include ‘C:INCLUDEWin32ax.inc’ section ‘.data’ data readable writeable szClsName db «TestWndClass»,0 szWindowName db «Tutorial #1»,0 wCls WNDCLASS wMsg MSG section ‘.code’ code readable executable MyEntry: mov [wCls.style],CS_VREDRAW+CS_HREDRAW mov [wCls.lpfnWndProc],WndProc mov [wCls.lpszClassName],szClsName mov [wCls.hbrBackground],COLOR_WINDOW+1 invoke RegisterClass,wCls invoke CreateWindowEx,0,szClsName,szWindowName,WS_VISIBLE or WS_SYSMENU, 200,200,200,200,0,0,0,0 .while eax<>0 invoke GetMessage,wMsg,0,0,0 push eax invoke TranslateMessage,wMsg invoke DispatchMessage,wMsg pop eax .endw invoke ExitProcess,0 proc WndProc hWnd,uMsg,wParam,lParam push edi esi ebx mov eax,[uMsg] .if eax=WM_CLOSE invoke PostQuitMessage,0 .elseif eax=WM_CREATE .else invoke DefWindowProc,[hWnd],[uMsg],[wParam],[lParam] .endif pop ebx esi edi ret endp section ‘.idata’ import data readable writeable library kernel32, ‘KERNEL32.DLL’, user32, ‘USER32.DLL’ include ‘C:INCLUDEAPIAKernel32.inc’ include ‘C:INCLUDEAPIAUser32.inc’

Это шаблоны приложений. Но начинающим будет интересно увидеть и простые конструкции кода. Потому представлю и простейшие конструкции:
if(eax==10) ebx=1;

cmp eax,10 jne NO mov ebx,1 NO: ;;##Суть конструкции проста. Если eax!=10 мы перепрыгнем к метке ;;##которая идет после команд которые должны выполнится если eax==10.
for(int i=100;i>0;i—)
szBuff[ i ]=0;
>
mov ecx,100 cycle: mov byte[szBuff+ecx],0 loop cycle ;;## В ECX содержится счетчик который будет декрементироватся при ;;##каждой итерации цикла. Т.е. в данном случае ;;##мы заполняем массив с конца. ;;##

PS: Хотел в одно сообщение но форум резонно возразил что 8000+ символов для одного сообщения это слишком много, надеюсь этот материал хоть кому то поможет.
PSS: Прошу закрепить тему.

«Тяжело в учении, легко в бою» — А.В. Суворов
Последний раз редактировалось Ivan_32; 26.06.2009 в 14:32 .
Форумчанин
Регистрация: 15.07.2008
Сообщений: 615
Продолжу тему .
Вот пример создания простого окна сообщения(MessageBox) на MASM’е:

.386 .model flat,stdcall option casemap:none include masm32includewindows.inc include masm32includekernel32.inc includelib masm32libkernel32.lib include masm32includeuser32.inc includelib masm32libuser32.lib .data MsgBoxCaption db «Первая прога под Win_32»,0 MsgBoxText db «Hello world. «,0 .code start: invoke MessageBox, NULL, addr MsgBoxText, addr MsgBoxCaption, MB_OK invoke ExitProcess, NULL end start
Вся программа заключается всего в одной строчке кода:
invoke MessageBox, NULL, addr MsgBoxText, addr MsgBoxCaption, MB_OK

1)invoke MessageBox-говорит компилятору что мы вызываем API-ф-ию MessageBox
2)NULL-это стиль нашего окошка( можно написать и 0, ничего не изменится)
3)addr MsgBoxText, addr MsgBoxCaption-это текст окна/заголовка
4)MB_OK-окно только с кнопкой Ok
5)invoke ExitProcess, NULL- это API-ф-ия выхода, после того когда мы нажмем на Ok

Теперь запишем наше окошко уже не с помощью API, а на языке Ассемблера:

.386 .model flat,stdcall option casemap:none include masm32includewindows.inc include masm32includekernel32.inc includelib masm32libkernel32.lib include masm32includeuser32.inc includelib masm32libuser32.lib .data MsgBoxCaption db «Первая прога под Win_32»,0 MsgBoxText db «Hello world. «,0 .code start: push 0 push offset MsgBoxCaption ; смещение строки заголовка push offset MsgBoxText ; смещение строки текста push 0 ; стиль окна call MessageBox push 0 ; нулевой(пустой) параметр для call ExitProcess ; ф-ии выхода из программы end start
В следующий раз попробуем создать разными путями окошко под Винду
xor eax , eax
xchg [ eax ], eax
Последний раз редактировалось MalCer; 10.07.2009 в 22:03 .
Участник клуба
Регистрация: 06.04.2009
Сообщений: 1,524
Хочу, заметить один факт.
При передаче параметров в MessageBox
push 0 push offset MsgBoxCaption ; смещение строки заголовка push offset MsgBoxText ; смещение строки текста push 0

Параметры передаются с право налево. Т.е. (если функция выглядит так MessageBox (HWND Handle, LPCSTR lpText, LPCSTR lpCaption, UINT uType) сначала передается стиль кнопок, потом текст заголовка, потом текст и только потом хендл.

push 0 ; Стиль кнопок (в данном случае MB_OK) (uType) push offset MsgBoxCaption ; смещение строки заголовка (lpCaption) push offset MsgBoxText ; смещение строки текста (lpText) push 0 ; Handle окна (Handle)

И так во всех функциях на асме.
Удачи в изучении.
P.S. Где-то есть хороший справочник по асму. Как найду выложу

добрый няша
Регистрация: 29.10.2006
Сообщений: 4,804
И так во всех функциях на асме.
нет, только у тех которые вызываются по соглашению stdcall

[Программирование на ассемблере на платформе x86-64]
Участник клуба
Регистрация: 06.04.2009
Сообщений: 1,524

Читайте также:
Как пробежать 10 км программа

нет, только у тех которые вызываются по соглашению stdcall

Форумчанин
Регистрация: 15.07.2008
Сообщений: 615
Создание окна

.386 .model flat,stdcall ; определяем, что у нас сплошная(«плоская») модель памяти, ;а stdcall говорит, что нужно уровнять стэк, после того как ф-ия будет прервана option casemap:none; включае эту ф-ию, чтобы различать в каких регистрах написана ф-ия ;############################################ ; подключили библиотеки include masm32includewindows.inc include masm32includeuser32.inc include masm32includekernel32.inc includelib masm32libuser32.lib includelib masm32libkernel32.lib ;############################################# ; Объявили главную процедуру, которая будет состоять из 4 параметров WinMain proto :DWORD,:DWORD,:DWORD,:DWORD ; Инициализируем сегметнт данных .data ClassName db «SimpleWinClass»,0 ; Имя нашего класса окна NameWindow db «Мое первое окно на ассемблере. «,0 ; Имя окна .data? ; неинициализируемые данные hInstance HINSTANCE ? ; хендл программы CommandLine LPSTR ? ; обработка командной строки ; начало секции, где будет располагаться код .code start: invoke GetModuleHandle, NULL ; берем хэндл нашей программы mov hInstance,eax ; сохраним значение eax в переменную хэндл invoke GetCommandLine ; вызвать командную строку mov CommandLine,eax ; обрабатываем командную строку ; вызываем основную функцию(4 параметра) invoke WinMain, hInstance, NULL, CommandLine, SW_SHOWDEFAULT; вызываем нашу ; основную функцию invoke ExitProcess, eax ; выйти из программы ; Начнем основные действия с описания процедуры WinMain proc hInst:HINSTANCE, hPrevInst:HINSTANCE, CmdLine:LPSTR, CmdShow:DWORD LOCAL wc:WNDCLASSEX ; создаем 3 локальные переменные в стэке LOCAL msg:MSG LOCAL hwnd:HWND ; далее слует так: вызывается до точки член, а после его параметр mov wc.cbSize, SIZEOF WNDCLASSEX ; размер структуры mov wc.style, CS_HREDRAW or CS_VREDRAW ; стиль окна(у нас их 2) mov wc.lpfnWndProc, offset WndProc ; получим адрес процедуры окна, создаваемых из класса. mov wc.cbClsExtra, NULL ; кол-во резервиремых байт mov wc.cbWndExtra, NULL push hInstance ; в стэк наш хэндл pop wc.hInstance ; извлекем из стэка переменную хэндл mov wc.hbrBackground, COLOR_WINDOW+1 ; цвет окна(белый) mov wc.lpszMenuName, NULL ; хэндл меню для окон, созданных из класса по умолчанию mov wc.lpszClassName, offset ClassName ; получаем имя класса окна invoke LoadIcon, NULL, IDI_APPLICATION ; вызываем API-функцию создания обычной(стандартной) ; иконки Windows mov wc.hIcon, eax ; хэндл иконки mov wc.hIconSm, eax ; хэндл для маленькой иконки invoke LoadCursor, NULL, IDC_ARROW ; вызываем API-функцию для создания курсора mov wc.hCursor, eax ; хэндл курсора invoke RegisterClassEx, addr wc ; регистрируем класс окна INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR NameWindow, ; вызываем API-функцию для создания окна(ф-ия имеет 12 параметров) WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL, hInst,NULL mov hwnd, eax ; значение eax в нашу переменную(хэндл), т.к. eax будет использоваться в дальнейшем invoke ShowWindow, hwnd,SW_SHOWNORMAL ; вызываем API-функцию , которая устанавливает состояние показа определяемого окна invoke UpdateWindow, hwnd ; вызываем API-функцию , которая модифицирует клиентскую область .WHILE TRUE ; используем цикл сообщений(чтобы обработать эти самые сообщения, иначе у нас не будет контакта с окном) invoke GetMessage, ADDR msg, NULL, 0, 0 ; вызываем API-ф-ию,которая последовательно проверяется, есть ли сообщения от Windows. .BREAK .IF (!eax) invoke TranslateMessage, ADDR msg ; API-ф-ия, которая обрабатывает ввод с клавиатуры и генерирует новое сообщение invoke DispatchMessage, ADDR msg ; API-ф-ия, которая пересылает сообщение процедуре соответствующего окна .ENDW ; конец цикла mov eax, msg.wParam ; код выхода сохраняется в члене MSG структуры wParam ret ; выйдем из процедуры WinMain WinMain endp ; конец процедуры WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM ; процедура окна .if uMsg==WM_DESTROY ; посылаем сообщение функции, которая нужна чтобы уничтожить(закрыть) окно invoke PostQuitMessage, NULL ; это API функция , обрабатывающая сообщения, которыми ваша программа не нуждается .else ; иначе. invoke DefWindowProc, hWnd, uMsg, wParam, lParam ; вызываем DefWindowProc, которая ;обеспечивает обработку по умолчанию любого сообщения окна, которые приложение не обрабатывает ret ; пометим адрес возврата .endif ; конец условия xor eax, eax ; устанавливаем eax в 0 ret ; адрес возврата из WndProc WndProc endp ; окончателььно выходим из процедуры end start; конец всей программы
xor eax , eax
xchg [ eax ], eax
Участник клуба
Регистрация: 02.05.2009
Сообщений: 1,605

Раз пошли такие дела, то я тоже поддержу
В этой программке для масма создается окно, на котором находится поле edit, со стилем ES_PASSWORD(вместо букв на экране будут появлятся звездочки) и кнопка, нажав на которую можно увидеть, какой текст ввели. Кроме того в ней класс окна уже заполнен, а не заполняется по ходу программы.

Какой вопрос — такой ответ. Не забываем пользоваться поиском, гуглом.
Помощь в выполнении работ по ассемблеру ICQ:2725322O4

Последний раз редактировалось Goodwin98; 20.07.2009 в 17:24 .

Источник: www.programmersforum.ru

4. Выполнение (запуск) программы

Запуск .EXE-программы может быть осуществлён с помощью двойного щелчка мышью.

Если вы создали программу, которая ничего не выводит на экран, то за её работой можно наблюдать при помощи программы-отладчика, например, OllyDbg. Отладчики позволяют наблюдать за изменением содержимого регистров и флагов. Подробнее работа в отладчике OllyDbg будет описана ниже.

2.4. Инструментальный пакет masm32

В п.2.3 отмечено, что для создания программ на ассемблере в Windows, необходим текстовый редактор и компилятор. Реальные программы Win32 используют также внешние функции, стандартные константы и переменные, ресурсы и много другое. Всё это требует дополнительных файлов, которые есть в инструментальном пакете MASM32. Важно понять, что MASM32 не компилятор, а сборник для программирования под Win32, в который входит 32-битный компилятор MASM.

Инструментальный пакет MASM32 предназначен для создания приложений Windows на языке ассемблера и содержит все необходимые инструменты, к тому же он распространяется бесплатно.

Основные сведения и порядок работы в пакете masm32:

1. Для создания исходных текстов программ рекомендуется использовать текстовый процессор пакета MASM32 под названием QEDITOR (от Quick Editor, быстрый редактор):

После набора сохранить текст программы командой File – Save, указать папку BIN и расширение .ASM, например MYPROG.ASM.

2. Командой Project – Build All создать объектный и исполнимый файлы:

Если исходный текст программы набран без ошибок, то в папке, где он хранился, увидим два новых файла: MYPROG.OBJ и MYPROG.EXE.

3. Когда объектный и исполнимый файлы созданы, запустите программу на выполнение. Для этого можно дважды щелкнуть мышью по названию исполнимого файла (в папке BIN) или запустить программу через редактор QEDITOR командой Project – Run Program.

2.5. Примеры

Пример 0. «Скелет» стандартной программы

.model flat, stdcall

option casemap :none

;подключение необходимых библиотек

include MASM32INCLUDEwindows.inc

include MASM32INCLUDEmasm32.inc

include MASM32INCLUDEgdi32.inc

include MASM32INCLUDEuser32.inc

include MASM32INCLUDEkernel32.inc

includelib MASM32LIBmasm32.lib

includelib MASM32LIBgdi32.lib

includelib MASM32LIBuser32.lib

includelib MASM32LIBkernel32.lib

;раздел, где объявляются все константы

;раздел, где объявляются переменные, уже имеющие какое-то значение

;раздел, где объявляются переменные, еще не имеющие значения

start: ;с этого слова начинается код программы

invoke ExitProcess,0

end start ;с этого слова заканчивается код программы

Сохраните этот «скелет» в отдельном файле для удобства и используйте как заготовку.

Пример 1. Структура программы и основные директивы

Построчно разберём простейшую программу.

Текст программы на ассемблере содержит кроме инструкций процессору еще и служебную информацию (в виде директив), предназначенную для программы-ассемблера.

Читайте также:
Через какую программу залить винду на флешку

Начнем с простого. В первой программе не будет вызовов API-функций, ее цель – понять саму структуру программы на языке ассемблера для Windows. Поэтому программа, прибавляющая к 2 число 3, будет выглядеть следующим образом:

.model flat, stdcall

mov eax, 8

add eax, 8

end start

В ней инструкции процессора mov, add, ret окружены директивами. Первые три директивы начинаются с точки.

Директива .386 показывает, для какого процессора предназначена программа. В нашем случае это процессор Intel 80386 и более поздние модели, ведь семейство процессоров Intel совместимо снизу вверх.

Вторая директива .model flat, stdcall показывает, в какой среде будет работать программа. Все программы работают под управлением операционной системы, которая их запускает и обеспечивает взаимодействие с внешней средой. Директива .model задаёт модель памяти flat (плоская или сплошная) для нашей программы. Эта модель памяти используется для программирования под Windows, т.е. директива говорит о том, что именно для операционных систем семейства Windows 95 2 предназначена программа.

Stdcall — это «уговор» о том, кто будет чистить параметры (функция, которую вызвали, или сам вызывающий). Мы всегда будем использовать вариант «функция чистит свои параметры». Он и называется stdcall. Однако такое объяснение не полное, и мы вернемся к параметру stdcall при объяснении вызова функций. К этому моменту вы уже будете знать, что такое стек.

Третья директива .code показывает, где начинаются сами команды процессора. Когда операционная система пытается запустить программу, она ищет в ней инструкцию, с которой нужно начать, и отправляет ее процессору. Когда же инструкции кончаются, операционная система «подхватывает» программу и помогает ей правильно завершиться, чтобы освободить место другим, ведь Windows – многозадачная операционная система, способная выполнять одновременно несколько программ. Уйти из-под «опеки» операционной системы помогает инструкция ret.

Инструкция, с которой начинается программа, обычно помечается последовательностью символов с двоеточием на конце (меткой). В нашем случае это start:. Там, где оканчивается последовательность команд процессора, в программе должна стоять директива end , в нашем случае это end start. Эта директива, а также сама метка не переводятся в инструкции ассемблера, а лишь помогают получить программу, которую способен выполнить процессор. Без них программа-ассемблер не поймет, с какой инструкции процессор начнет работу.

Отладка

Программа ничего не выводит на экран, поэтому за для изучения её работы воспользуемся программой-отладчиком OllyDbg. Чтобы открыть программу в отладчике, достаточно загрузить OllyDbg и открыть программу как обычный документ – File-Open.

В верхней левой части отладчика можно увидеть свою программу. Вверху справа – регистры процессора.

Внизу слева — байты памяти (OllyDbg сразу же показывает секцию данных программы). Внизу справа отображается содержимое стека (работа со стеком будет описана ниже).

Необходимо помнить, что Ollydbg это отладчик и у него есть свои ограничения. Рекомендуется закрывать его каждый раз перед загрузкой новой программы.

С помощью клавиши F8 можно выполнить программу по шагам и просмотреть, как меняется содержимое регистров. Ответьте на вопрос, почему в результате сложения 8+8 регистр EAX стал равен 10? Состояние флагов также меняется. Мы видим, что после выполнения первой команды флаг Z опустился (обратился в ноль), потому что результат выполнения операции не равен нулю.

Пример 2. Использование функций API

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

API – это стандартные функции, на основе которых и пишут все программы для Windows. Например MessageBox выдаёт сообщение на экран, PostQuitMessage сообщит Windows, что программа хочет закончить работу и т.д. Все они уже готовы – остается только вызывать их. Получается, что используя API-функции, мы применяем элементы программирования высокого уровня.

Находятся API-функции обычно в динамически загружаемых библиотеках – файлах с расширением .DLL.

При вызове каждой API-функции надо передавать параметры, т.е. аргументы, с которыми ей предстоит работать. Раньше это делалось так: параметры заталкивались в стек (команда push) задом наперед – сначала последний, потом предпоследний и т.д., а затем вызывалась сама программа (команда call). Например:

push addr Text2

push addr Text1

call MessageBox

Такая запись допускается и сейчас, но существует и более компактная: invoke MessageBox, hWnd, Text1, Text2

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

Рассмотрим программу с использованием функций API. Прежде чем приступить к выводу на экран, изучим более простую процедуру ExitProcess. Её вызывает каждая Windows-программа, чтобы завершить свою работу. В ассемблере под DOS мы пользовались инструкцией возврата ret. Но ExitProcess действует правильнее, не только возвращая управление операционной системе, но и освобождая занятые программой ресурсы.

В следующем листинге показана программа для Windows, которая только и делает, что правильно завершается.

.model flat, stdcall

option casemap:none

includelib C:MASM32LIBkernel32.lib

ExitProcess proto :DWORD

call ExitProcess

Вызываемая в ней процедура ExitProcess требует одного параметра – это код завершения, возвращаемый операционной системе. Он передается процедуре командой push 0. Число 0 считается признаком удачного завершения.

Поскольку ExitProcess – «чужая» процедура, не определенная в нашей программе, ассемблер должен знать, где она находится, а также (для проверки – она ли это) число и размер ее параметров.

Сведения об адресе и параметрах процедуры хранятся в файле библиотеки kernel32.lib, который подключается к ассемблерному тексту директивой includelib C:MASM32LIBkernel32.lib.

Перед тем как создать инструкцию вызова этой процедуры компоновщик сравнивает сведения из библиотеки с прототипом ExitProcess proto :DWORD, и если все совпадает, создает пригодный к исполнению файл с расширением .EXE. Прототип процедуры очень прост и состоит из имени, слова proto и параметров. В нашем случае параметр один – это двойное слово (то есть 4 байта) DWORD. Если параметров несколько, они разделяются запятой.

Пример 3. Вывод строки на экран

Создадим программу, выводящую на экран фразу “Hello, world!”:

.model flat, stdcall

option casemap:none

ExitProcess proto :dword

GetStdHandle proto :dword

WriteConsoleA proto :dword, :dword, :dword, :dword, :dword

includelib C:MASM32LIBkernel32.lib

msg db “Hello, world!”, 0dh, 0ah

cWritten dd ?

invoke GetStdHandle, -11

mov stdout, eax

invoke WriteConsoleA, stdout, ADDR msg, sizeof msg, ADDR cWritten, 0

invoke ExitProcess, 0

end start

В программе вызываются три процедуры: GetStdHandle, WriteConsoleA и ExitProcess.

Источник: studfile.net

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru