Ассембли. Урок IV - Переменные и возвращаемые значения функций
Приветствую... Сегодняшний урок посвящённ переменным и значениям, которые возвращают функции API. Для более подробного понимания материала
воспользуемся всё той-же функцией MessageBox. Вы можете спросить: что может возвращать простое окно сообщения? А возвращает она одно из следующих
значений:
IDABORT ; нажата кнопка ABORT
IDCANCEL ; нажата кнопка CANCEL
IDIGNORE ; нажата кнопка IGNORE
IDNO ; нажата кнопка NO
IDOK ; нажата OK
IDRETRY ; нажата RETRY
IDYES ; нажата кнопка YES
Более подробную информацию по функциям API можно найти на MSDN (http://msdn2.microsoft.com/ru-ru/default.aspx), или в любом справочнике который
поставляеться с продуктами от Borland. Посмотрим на следующий код:
include 'D:\FASM\include\win32ax.inc'
.code
start:
invoke MessageBox,0,'привет!','заголовок', MB_OK ; вызываем окошко
invoke ExitProcess,0 ; завершаем процесс
.end start
Посмотрите стиль окошка - MB_OK, соответственно окошко выскочит с одной кнопкой OK. И если мы нажмём OK то функция возвратит IDOK. Но что если нам
нужно например использовать две кнопки, например OK & CANCEL. Для этого есть специальный стиль окна - MB_OKCANCEL. Вообще они конечно описаны в MSDN,
так что я не буду их приводить в этом тексте. Пример:
include 'D:\FASM\include\win32ax.inc'
.code
start:
invoke MessageBox,0,'привет!','заголовок', MB_OKCANCEL ; вызываем окошко
invoke ExitProcess,0 ; завершаем процесс
.end start
Тогда, соответственно при выполнении этого кода, если мы нажали на OK, функция возвратит IDOK, если CANCEL - то получим IDCANCEL. Чтобы узнать что
возвращает та или иная функция - обратитесь к MSDN (для этого знание технического английского вам поможет). Кстати функции возвращают значения через
регистр EAX почти всегда. Так что, чтобы проверить возвращаемое значение - нужно проверить именно регистр EAX. Давайте сделаем проверку, при которой
если мы нажимаем например на OK выскакивает окошко и говорит нам что мы нажали именно эту кнопку, если CANCEL - то соответственно сообщение будет
другим:
include 'D:\FASM\include\win32ax.inc'
.code
start:
invoke MessageBox,0,'привет!','заголовок', MB_OKCANCEL ; вызываем окошко
cmp eax,IDOK ; проверяем что нажали ok
jz OK_PRESSED ; если да - прыгаем на соответствующее сообщение
invoke MessageBox,0,'вы нажали CANCEL','заголовок',MB_OK ; если нет - то не прыгаем и выводим что нажали CANCEL
jmp EXIT ; прыгаем на выход чтобы избежать появления второго окна
OK_PRESSED:
invoke MessageBox,0,'вы нажали OK','заголовок',MB_OK ; выводим сообщение про OK
EXIT:
invoke ExitProcess,0 ; завершаем процесс
.end start
Надеюсь из комментариев всё ясно, но на всякий случай поясню, что после того как мы вивели окно с приветствием, мы проверяем с помощью оператора CMP,
значение регистра EAX и если там IDOK то прыгаем на сообщение и говорим что нажали OK, иначе выводим сообщение что нажали CANCEL и прыгаем на метку
EXIT дабы избежать появления второго окна, ведь код продолжит выполняться и наткнёться на строку invoke MessageBox,0,'вы нажали OK','заголовок',MB_OK
. То есть инструкцией jmp (безусловный переход) мы перепрыгиваем эту запись и выходим из программы.
Теперь займёмся переменными:
Переменные должны быть обьявлены в секции данных - .data . Сначала мы пишем имя переменной потом через пробел - её размер, и только потом через пробел
её значение. Пример:
include 'D:\FASM\include\win32ax.inc'
.data
perem1 dd 0
.code
start:
invoke ExitProcess,0
.end start
В этом примере мы обьявили переменную perem1 размером в 4 байта (dd - define dword (двойное слово - 4 байта)) и присвоили ей значение 0 (нуль). Теперь
в неё можно писать данные, но не более 4 байт, так как мы задали размер именно в 4 байта. Можно считывать значение переменной итд. Кстати, для того
чтобы считать значение переменной, её нужно обрамить скобками вот так:
include 'D:\FASM\include\win32ax.inc'
.data
perem1 dd 0
.code
start:
mov eax,[perem1]
invoke ExitProcess,0
.end start
Но чтобы считать её адрес в памяти - обрамление скобками не требуеться. Пример:
include 'D:\FASM\include\win32ax.inc'
.data
perem1 dd 0
.code
start:
mov eax,perem1
invoke ExitProcess,0
.end start
Давайте теперь примерим всё это на практике. Напимеш программу для вывода текста в окно при помощи переменных. Для этого рассмотрим параметры самой
функции, которые кстати вы можете и сами посмотреть в MSDN, но у меня мало трафика и я приведу кусок из справки от Borland:
int MessageBox(
HWND hWnd, // handle of owner window
LPCTSTR lpText, // address of text in message box
LPCTSTR lpCaption, // address of title of message box
UINT uType // style of message box
);
Из этого ясно что: Для текста в заголовке и для текста в окне, мы должны передавать не значения, а адреса переменных, которые этот текст содержат.
Сделаем это:
include 'D:\FASM\include\win32ax.inc'
.data
text db "наш текст",00h
zagolovok db "заголовок",00h
.code
start:
invoke MessageBox,0,text,zagolovok,0
invoke ExitProcess,0
.end start
Обратите внимание как мы обьявляем строки - как массив байтов, которые заканчиваються нулевым байтом. Кстати db - это обьявить байт. Заметьте также,
что когда мы вызываем функцию - мы не обрамляем переменные скобками, то есть мы берём их адрес в памяти, а не их значения. Вот и всё. Пока...
-------------------------------------------------------------------
Вроде всё доходчиво описано... поймёт каждый. =)