Уроки Iczelion'а




Урок 2. MessageBox - часть 5


Давайте изменим msgbox.asm для отображения сообщения.

.386

.model flat,stdcall option casemap:none include \masm32\include\windows.inc include \masm32\include\kernel32.inc

includelib \masm32\lib\kernel32.lib include \masm32\include\user32.inc includelib \masm32\lib\user32.lib

.data MsgBoxCaption db "Iczelion Tutorial No.2",0 MsgBoxText db "Win32 Assembly is Great!",0

.code start:

invoke MessageBox, NULL, addr MsgBoxText, addr MsgBoxCaption, MB_OK invoke ExitProcess, NULL end start

Скомпилируйте и запустите. Вы увидите окошко с сообщением "Win32 Assembly is great!".

Давайте снова взглянем на исходник.

Мы определили две оканчивающиеся NULL'ом строки в секции .data. Помните, что каждая ANSI строка в Windows должна оканчиваться NULL'ом (0 в шестнадцатеричной системе). Мы используем две константы, NULL и MB_OK. Эти константы прописаны в windows.inc, так что вы можете обратиться к ним, указав их имя, а не значение. Это улучшает читабельность кода. Оператор addr используется для передачи адреса метки (и не только) функции. Он действителен только в контексте директивы invoke. Вы не можете использовать его, чтобы присвоить адрес метки регистру или переменной, например. В данном примере вы можете использовать offset вместо addr. Тем не менее, есть некоторые различия между ними.

1. addr не может быть использован с метками, которые определены впереди, а offset может. Hапример, если метка определена где-то дальше в коде, чем строка с invoke, addr не будет работать.

invoke MessageBox,NULL, addr MsgBoxText,addr MsgBoxCaption,MB_OK ...... MsgBoxCaption db "Iczelion Tutorial No.2",0 MsgBoxText db "Win32 Assembly is Great!",0

MASM доложит об ошибке. Если вы используете offset вместо addr, MASM без проблем скомпилирует указанный отрывок кода.

2. Addr поддерживает локальные переменные, в то время как offset нет. Локальная переменная - это всего лишь зарезервированное место в стеке. Вы только знаете его адрес во время выполнения программы. Offset интерпретируется во время компиляции ассемблером, поэтому неудивительно, что он не поддерживает локальные переменные. Addr же работает с ними, потому что ассемблер сначала проверяет - глобальная переменная или локальная. Если она глобальная, он помещает адрес этой переменной в объектный файл. В этом случае оператор работает как offset. Если это локальная переменная, компилятор генерирует следующую последовательность инструкций, перед тем как будет вызвана функция:

lea eax, LocalVar push eax

Учитывая, что lea может определить адрес метки в "рантайме", все работает прекрасно.

[C] Iczelion, пер. Aquila.






Содержание  Назад  Вперед